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; //没有断点,所有值都相等,则返回随便一个下标 }