今天是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]);
    }
};