搜索旋转排序数组 断点

leetcode 81题 

搜索旋转排序数组 II

旋转排序数组如[2,5,6,0,0,1,2],假如left为左端点,right为右端点,数组特点是左边单调不减,且所有元素大于等于left,右边单调不减,且所有元素小于等于left,中间只有一个位置下降

下降位置的特点是nums[mid] > nums[mid + 1]

由于可能有重复元素,导致mid和left值相等,相等时无法判断断点在左侧还是右侧,所以++left作下一次探测

另外要预处理掉数组size小于3(否则findpivot中可能mid可能越界)及数组单调递增情况

bool search(vector<int>& nums, int target) {
        int size(nums.size());
        if(size == 0) {
            return false;
        }
        if(size == 1) {
            return target == nums[0];
        }
        if(size == 2) {                     //确保findpivot中数组size大于2,否则可能因为mid-1/mid+1越界
            return target == nums[0] || target == nums[1];
        }

        int left(0), right(size-1);
        if(nums[left] < nums[right]) {      //预处理,数组递增没有断点情况
            return binary_search(nums.begin() + left, nums.begin() + right + 1, target);
        }

        int pivot = findpivot(nums, left, right);
        if(target >= nums[left]) {
            return binary_search(nums.begin(), nums.begin()+pivot, target);
        }
        else {
            return binary_search(nums.begin()+pivot, nums.end(), target);
        }
    }

    int findpivot(vector<int>& nums, int left, int right) {
        while(left <= right) {
            int mid = (left + right) / 2;
            if(mid+1 < nums.size() && nums[mid] > nums[mid + 1]) {  //断点较小值的下标
                return mid + 1;
            }
            if(mid-1 >= 0 && nums[mid - 1] > nums[mid]) {   //断点小值的下标
                return mid;
            }
            if(nums[mid] > nums[left]) {
                left = mid + 1;
            }
            else if(nums[mid] < nums[left]) {
                right = mid - 1;
            }
            else {
                ++left;         //mid和left元素相等
            }
        }
        return left;            //没有断点,所有值都相等,则返回随便一个下标
    }

 

posted @ 2020-03-05 18:07  wuzs  阅读(628)  评论(0编辑  收藏  举报