154. Find Minimum in Rotated Sorted Array II(题目链接)
Hard
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
(i.e., [0,1,2,4,5,6,7]
might become [4,5,6,7,0,1,2]
).
Find the minimum element.
The array may contain duplicates.
Example 1:
Input: [1,3,5] Output: 1
Example 2:
Input: [2,2,2,0,1] Output: 0
Note:
- This is a follow up problem to Find Minimum in Rotated Sorted Array.
- Would allow duplicates affect the run-time complexity? How and why?
方法1:二分法
这个题目类似于 153. Find Minimum in Rotated Sorted Array
解法:
class Solution:
def findMin(self, nums: List[int]) -> int:
l, r = 0, len(nums) - 1
while l < r:
m = (l + r) // 2
if nums[m] > nums[r]:
l = m + 1
else:
r = m
return nums[l]
区别在于,nums中的数字存在相同的数字,如果我们继续使用153题里面的做法,下面这种情况是没法处理的
nums = [10, 1, 10, 10, 10]
当nums[l] == nums[m] == nums[r] 二分法不知道往那边走,所以需要对代码做一些修改
思路:
当nums[mid] > nums[r]时,最小值一定存在于[mid + 1, r] 这个区间里。比如[4, 5, 6, 7, 1, 2, 3],nums[mid] = 7, 7 > 3, 最小的数1存在于[4, 6](这是nums的索引)
当nums[mid] < nums[r]时,最小值一定存在于[l, mid] 这个区间里。 比如[4, 5, 1, 2, 3], nums[mid] = 1, 1 < 3, 最小的数在区间 [2, 4]之间
当nums[mid] == nums[r] 时,我们可以将r左移以为,也就是r -= 1。这并不会影响我们继续找最小的数,因为我们去掉的是一个重复的数。
class Solution:
def findMin(self, nums: List[int]) -> int:
l, r = 0, len(nums) - 1
while l < r:
m = (l + r) // 2
# 这说明中间的数大于最左边的数,因为默认是从小到大排列的,说明mid-r之间存在最小的那个值
if nums[m] > nums[r]:
l = m + 1
elif nums[m] < nums[r]:
r = m
# 如果中间的那个数等于最右边的数,我们将r左移一位,不会差生影响,因为存在nums[mid]==nums[r]
# 我们去掉一个相同的数,不会影响找最小的那个数
else:
r -= 1
return nums[l]