154. Find Minimum in Rotated Sorted Array II***
https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/
题目描述
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 toFind Minimum in Rotated Sorted Array.
- Would allow duplicates affect the run-time complexity? How and why?
解题思路
和 153. Find Minimum in Rotated Sorted Array** 区别是: 原数组中有重复元素了.
思路 1: 来自 LeetCode 的讨论区: My pretty simple code to solve it, 和 nums[hi]
比较, 直接看实现吧.
思路 2: 我的思路, 从数组末尾开始, 将等于 nums[0]
的元素全部忽略, 然后使用 153. Find Minimum in Rotated Sorted Array** 的二分法, 找第一个小于 nums[0]
的结果.
C++ 实现 1
实现思路 1.
When num[mid] == num[hi]
, we couldn’t sure the position of minimum in mid’s left or right, so just let upper bound reduce one.
注意实现细节, nums[mid]
是和 nums[hi]
进行比较:
-
nums[mid] > nums[hi]
, 说明此时可以将lo = mid + 1
, 因为mid
此时指向数值较大的部分数组; -
nums[mid] < nums[hi]
, 此时可以将hi = mid
, 因为此时mid
指向的是数值较小的部分数组, 此时将hi
直接指向mid
即可; -
nums[mid] == nums[hi]
, 说明此时数组末尾存在重复值, 此时将hi --
, 尽量略过这些值.
class Solution {
public:
int findMin(vector<int> &num) {
int lo = 0;
int hi = num.size() - 1;
int mid = 0;
while(lo < hi) {
mid = lo + (hi - lo) / 2;
if (num[mid] > num[hi]) {
lo = mid + 1;
}
else if (num[mid] < num[hi]) {
hi = mid;
}
else { // when num[mid] and num[hi] are same
hi--;
}
}
return num[lo];
}
};
C++ 实现 2
使用 153. Find Minimum in Rotated Sorted Array** 中的代码和思路, 但是有一些需要改变的地方, 主要在于处理如下情况: [10, 1, 10, 10, 10]
, 如果直接使用 153 题的代码, 最后的结果是 10 而不是 1, 这是因为, 153 题中的代码首先确认的 mid 在 1 的索引后面(即 nums[mid]
等于 10), 那么之后代码就会在 1 后面的大量 10 中查找第一个小于 10 的元素, 但很明显, 这是不存在的, 此时 l
越界, 最后会返回 nums[0]
.
为了处理这种情况, 可以使用 while (nums[r] == nums[0]) r--
; 将右边的索引拉到第一个小于 10 的元素上来, 然后再进行搜索即可(可以直接用 153 题的代码了).
class Solution {
public:
int findMin(vector<int>& nums) {
int l = 0, r = nums.size() - 1;
// 只增加如下一行代码即可解决问题.
while (nums[r] == nums[0]) r --;
while (l <= r) {
int mid = l + (r - l) / 2;
if (nums[mid] >= nums[0])
l = mid + 1;
else
r = mid - 1;
}
return l >= nums.size() ? nums[0] : nums[l];
}
};