在看剑指offer时遇到了这个题目:寻找旋转排序数组中的最小值 II
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请找出其中最小的元素。
注意数组中可能存在重复的元素。
看到这个题目第一时间就想起了LeetCode81:搜索旋转排序数组 II。
首先先看看这两个题目的共同点:都是带有重复元素的旋转排序数组。
但他们的不同点在于:81题是寻找指定的数字,也就是说,这个target值得位置是不定的,它既可能位于左边的升序数组,也可能位于右边的升序数组。
而对于154题来说,这个target位置是固定的,这个值是旋转前数组的第一个值,旋转后它一定位于右边的升序数组。
这也就是这两个题目的最大的区别,对于81题来说,我们要不断通过判断left和righ与mid的值来缩小搜索空间直至寻找到。
而对于154题来说,我们只需要进行right和mid的对比,因为我们的target位于右边的升序数组,所以我们一切工作的目的也就是将搜索区间夹逼到右边数组。
如果在154题我们引入left与mid进行大小判断,这是无意义的,因为当nums[left]<nums[mid]时我们无法判断这个时候是left和mid两个都位于左边的升序数组还是右边的升序数组。
而对于right,如果mid的值小于right,说明一定在右边的升序数组,此时让right=mid来缩小夹逼范围(如果right=mid-1可能会错过)
而如果mid的值大于right,说明mid一定在左边,则令left=mid+1。
而如果mid==right的值,只要让right--,能继续循环即可以.
另外剑指offer在这个题里,当遇见相等时使用的是线性搜索。
class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { auto& nums=rotateArray; int low=0,high=nums.size()-1; int mid=low; while(low<high) { mid=(low+high)/2; if(nums[mid]<nums[high]) high=mid; else if(nums[mid]>nums[high]) low=mid+1; else high--; } return nums[low]; } };
从这两个题目里可以了解到,对于这种二分查找的题目,更重要的是根据target来调整夹逼搜索范围,比如154中已知target一定位于右边的升序数组,则只要与right对比就可以了。
LeetCode81:搜索旋转排序数组 II 与 LeetCode154:寻找旋转排序数组中的最小值 II
原文:https://www.cnblogs.com/lxy-xf/p/11337835.html