Typescript-Algorithms
    Preparing search index...

    Variable find_minimum_in_rotated_sorted_arrayConst

    find_minimum_in_rotated_sorted_array: (nums: number[]) => number = findMin

    153.寻找旋转排序数组中的最小值

    已知一个长度为 n 的数组,按升序排列,数组中的值 互不相同 。

    在传递给函数之前,数组在预先未知的某个下标 k(0 <= k < n)上进行了旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标从 0 开始计数)。

    给你旋转后的数组 nums ,请你找出其中最小的元素。

    你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。


    输入: nums = [3,4,5,1,2]

    输出: 1


    输入: nums = [4,5,6,7,0,1,2]

    输出: 0


    输入: nums = [11,13,15,17]

    输出: 11


    • n == nums.length
    • 1 <= n <= 5000
    • -5000 <= nums[i] <= 5000
    • 数组中所有整数 互不相同
    • 数组原本是一个升序数组,但在预先未知的某个点上进行了旋转

    </rewritten_file>

    Type declaration

      • (nums: number[]): number
      • Parameters

        • nums: number[]

        Returns number

    由于原数组是严格升序的,所以旋转 1 次和旋转多次的结果是类似的:最终数组要么是一个完整的升序数组(即未旋转时的原数组),要么是两个升序数组的组合。 这两个升序数组的组合形式是:[较大的升序段 + 较小的升序段],其中较小的升序段的第一个元素就是整个数组的最小值。

    使用二分查找,每次通过比较中值 nums[mid] 与 nums[right] 来判断中值 mid 属于哪个升序段:

    • 如果 nums[mid] < nums[right]:说明 mid 位于右升序段(即较小的升序段),mid 可能是最小值,因此将 right 更新为 mid。
    • 否则(nums[mid] > nums[right]):说明 mid 位于左升序段(即较大的升序段),此时最小值一定在 mid 右侧,因此将 left 更新为 mid + 1
    • 当 left == right 时,说明找到了最小值,直接返回 nums[left] 即可。所以循环不变的条件是:while(left < right)而不是while(left <= right)。区间收缩到剩下一个元素时停止。

    因为这是一个旋转之后的递增序列:

    • 用 mid 和 left 比较时:mid > left,无法确定最小值在 mid 的左边还是右边。
    • 用 mid 和 right 比较时:
    • 如果 mid > right,说明最小值在 mid 的右边(不包含 mid,因为 right 比 mid 小)。
    • 如果 mid <= right,说明右边是有序的(或者干脆只有一段递增区间,旋转回来了),且最小值就是 mid 或在 mid 的左边(包含 mid)。