二分查找可以按照区间来进行定位,比如说如下图
前半部分的红色区间和后半部分的绿色区间,红色区间的结束点a和绿色区间的开始点b
如果我们要查找红色区间点a,我们可以将二分法写成如下形式
int bs1(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (判断条件) l = mid;
else r = mid - 1;
}
return l;
}
反之,如果我们要查找绿色区间的开始点b,我们可以把区间写成如下形式
int bs2(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (判断条件) r = mid;
else l = mid + 1;
}
return l
}
按照以上两种方法,最终分别可以定位到区间a和b
(lc53)假设按照升序排序的数组在预先未知的某个点上进行了旋转。例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] 。
请找出其中最小的元素。
我们可以以nums[0]的值作为判断条件,将数组分为两个区间,前半部分>=nums[0],后半部分小于nums[0]
这样我们就可以定位到区间的分界点
class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.size() == 1) return nums[0];
int l = 0, r = nums.size()-1;
while(l < r){
int mid = (l + r + 1) >> 1;
if(nums[mid] >= nums[0]) l = mid;
else r = mid - 1;
}
if(l == nums.size()-1){ //注意边界情况
if(nums[l] >= nums[0]) return nums[0];
else return nums[l];
}
return nums[l+1];
}
};