20210408 LeetCode 每日一题(寻找旋转排序数组中的最小值)

170 阅读1分钟

题目描述

原题链接:寻找旋转排序数组中的最小值

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]

  • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]

    注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

示例

输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。

解答

遍历的方法就不说了,复杂度 O(n),这类题最主要的还是考察二分法,二分法的套路都差不多,只要找准了终止条件和比较规则就好做了。

在本题中,我们每次取中间的数与二分的最后一个数进行比较

- 如果中间数小于或等于末尾数,表明最小数在前半部分
- 如果中间数大于末尾数,表明最小数在后半部分
- 如果中间数等于就直接返回这个答案了

最终代码实现如下:

/**
 * @param {number[]} nums
 * @return {number}
 */
var findMin = function (nums) {
  let start = 0,
    end = nums.length - 1,
    mid
  while (start <= end) {
    mid = start + ~~((end - start) / 2)
    if (nums[mid] <= nums[end]) {
      end = mid
    } else if (nums[mid] > nums[end]) {
      start = mid + 1
    } else {
      return nums[mid]
    }
  }
  return nums[mid]
}

复杂度分析:

  • 时间复杂度:O(logN),二分查找
  • 空间复杂度:O(1)