Skip to content

Latest commit

 

History

History
117 lines (86 loc) · 3.65 KB

154-find-minimum-in-rotated-sorted-array-ii.md

File metadata and controls

117 lines (86 loc) · 3.65 KB

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

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]
  • 若旋转 7 次,则可以得到 [0,1,4,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 ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素

 

示例 1:

输入:nums = [1,3,5]
输出:1

示例 2:

输入:nums = [2,2,2,0,1]
输出:0

 

提示:

  • n == nums.length
  • 1 <= n <= 5000
  • -5000 <= nums[i] <= 5000
  • nums 原来是一个升序排序的数组,并进行了 1n 次旋转

 

进阶:

Solutions

类似题目:

1. 暴力

直接找到连接点。

时间复杂度 O(n); 空间复杂度 O(1)

class Solution:
    def findMin(self, nums: List[int]) -> int:
        n = len(nums)
        p = 0

        while p + 1 < n and nums[p] <= nums[p + 1]:
            p += 1

        return nums[0] if p == n - 1 else nums[p + 1]

2. 二分法

对半分为两半,因为相等缘故,没有办法区分哪组是有序的。如 a = [4, 5, 1, 4, 4, 4, 4],没有办法区分在 a[:3] 还是在 a[3:]。 这时可以左右都往里走一位。变成 a = [5, 1, 4, 4, 4]

平均时间复杂度为 O(log n); 空间复杂度为 O(1)

class Solution:
    def findMin(self, nums: List[int]) -> int:
        n = len(nums)
        l, r = 0, n - 1
        while l < r:
            m = (l + r) // 2
            if nums[l] == nums[m] and nums[r] == nums[m]:
                l += 1
                r -= 1
            elif nums[m] <= nums[r]:
                r = m
            else:
                l = m + 1

        return nums[l]

题解中给出一个方案。在 153. 寻找旋转排序数组中的最小值——2. 二分查找 解法中增加一个分支, 如果 nums[m] == nums[r] 那就把 r 往左移动一位。

class Solution:
    def findMin(self, nums: List[int]) -> int:
        n = len(nums)
        l, r = 0, n - 1
        while l < r:
            m = (l + r) // 2
            if nums[m] < nums[r]:
                r = m
            elif nums[m] > nums[r]:
                l = m + 1
            else:
                r -= 1

        return nums[l]