LeetCode 154 Find Minimum in Rotated Sorted Array II
思路
- 本题和LeetCode 81和LeetCode 153类似。当left、mid和right指向的元素大小相同时,是不能确定搜索区间应该如何变化的。所以,办法是保证left、mid和right不会同时指向大小相同的元素。当mid != left && nums[left] == nums[mid]的时候,++left即可。因为当区间大小为2时,倘若出现最小值是left所指向的值的情况,此时不能++left,如果++left会错过最小值。
倘若输入序列是[1,1,1,1,2,1,1],最后返回的结果是2后面的第一个1。本题的解法一是完备的。
-
本题也可以关注右边界,但是这个解法是不完备的。对于[1,1,1,1,2,1,1],返回的结果是第一个1。
-
将解法二修改为完备的。显然,对于输入序列[1,1,1,1,2,1,1]。在right减为5时,left为0,此时left,mid和right指向的元素相同,right会被减为4。这就是解法2不完备的原因,此时应该不减right,应该检查right和right-1所指向的元素间的大小关系。如果nums[right] >= nums[right-1],说明此时的right并没有指向递增子序列的开头,可以自减right。如果nums[right] < nums[right-1],说明right指向递增子序列的开头,直接返回right即可。因为整个序列中,满足nums[right] < nums[right-1]的,只有这一处。
Note: 本题不能使用LeetCode 81中曾经用过的
if (nums[left] == nums[mid] && nums[mid] == nums[right]) {
--right;
++left;
continue;
}
原因是,LeetCode 81是查找target是否存在,且在上述条件判断前,先检查了target是否等于nums[mid]。而本题是找到最小值,这一值是肯定存在的,上述条件会导致错过最小值,特别是当[left, right]的区间长度为2时。
代码
解法一
class Solution {
public:
int findMin(vector<int>& nums) {
int mid, left = 0, right = nums.size() - 1;
while (left < right) {
mid = left + (right - left) / 2;
if (mid != left && nums[left] == nums[mid]) ++left;
else if (nums[mid] < nums[left]) {
++left;
right = mid;
}
else if (nums[mid] > nums[right]) {
left = mid + 1;
}
else {
right = mid;
}
}
return nums[left];
}
};
解法二
class Solution {
public:
int findMin(vector<int>& nums) {
int left = 0, right = nums.size() - 1, mid;
while (left < right) {
mid = left + (right - left) / 2;
if (nums[mid] < nums[right]) {
right = mid;
}
else if (nums[mid] > nums[right]) {
left = mid + 1;
}
else {
--right;
}
}
return nums[left];
}
};
解法三
class Solution {
public:
int findMin(vector<int>& nums) {
int left = 0, right = nums.size() - 1, mid;
while (left < right) {
mid = left + (right - left) / 2;
if (nums[mid] < nums[right]) {
right = mid;
}
else if (nums[mid] > nums[right]) {
left = mid + 1;
}
else {
if (right > 0 && nums[right] >= nums[right - 1])
--right;
else return nums[right];
}
}
return nums[left];
}
};