今天是03/01.说实话,我个人非常讨厌二分搜索的题目,原因在于变种的二分搜索总是要理清楚不同情况下的+1,-1
事实上我觉得我可能从来没有愿意去弄清楚,所以在处理这种题目的时候,我一般都很随缘。
描述:
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.
I.you can assume there is no duplicate
II. what if there are duplicates ?
解答:
上面关于这道典型的二分搜索的题目,在不重复的情况下,还是非常easy的。引入重复后,在每一次判断前检查一下left和right临近的值
是否不同,如果不同,则回到了不重复的情况,如果相同,则按照区间减小的方向++ 或者 -- 删除完重复值。值得注意的还有两点:
1.外面的while 要求l<r-1,所以我们操作完l 和 r 之后检查一下是否可以直接跳出while。
2.可能pivot就在重复值之间,在开始之前我们先把这种可能性去掉。
代码:
不重复情况下:
class Solution {
public:
int findMin(vector<int>& nums) {
int n = nums.size();
int l(0),r(n-1);
while(l<r-1){
int mid = l + (r-l)/2;
if(nums[mid]>nums[l] && nums[mid]>nums[r]){
l = mid+1;
}
else r = mid;
}
return min(nums[l],nums[r]);
}
};
出现重复情况下:
class Solution {
public:
int findMin(vector<int>& nums) {
int n = nums.size();
int l(0),r(n-1);
while(nums[r]==nums[l] && l < r-1) r--;
while(l<r-1){
while(nums[l+1]==nums[l]) l++;
while(nums[r-1]==nums[r]) r--;
if(r-l<2) break;
int mid = l + (r-l)/2;
if(nums[mid]>nums[l] && nums[mid]>nums[r]){
l = mid+1;
}
else r = mid;
}
return min(nums[l],nums[r]);
}
};