二分法的边界确定
二分法是非常重要的基础算法,但是经常就是一看就会,一写就废。
其实在写二分法的时候,很多时候都是卡在了边界的确定的问题上。在确定边界的时候,要仔细考虑区间是如何定义的,以及搜索的目标与区间的关系,这样边界的确定就能一目了然。
二分查找涉及的很多的边界条件,逻辑都比较简单。例如 while(left < right)
与 while(left <= right)
,right = middle
与right = middle - 1
。
while(left < right)
与while(left <= right)
表示[left,right)
和[left,right]
这样的两种搜索区间right = middle
表示下一次搜索包括middle
,而right = middle - 1
表示下一次搜索不包括middle
例如LeetCode 34、在排序数组中查找元素的第一个和最后一个位置需要使用二分法分别找出左边界和右边界,这个题目就是非常经典的二分法里面的边界问题。
左边界
//寻找左边界
int left=0;
int right=nums.size()-1;
while(left<=right){ //在闭区间[left,right]内搜索
int mid=(right-left)/2+left;
if(nums[mid]<target) //寻找左边界,在num[mid]小于target的时候,num[mid]就一定不是左边界
left=mid+1; //因此这里就给left赋值mid+1
else
right=mid-1;
}
int leftBoard=nums[left]==target?left:-1;
右边界
//寻找右边界
int left=0;
int right=nums.size()-1;
while(left<=right){ //在闭区间[left,right]内搜索
int mid=(right-left)/2+left;
if(nums[mid]>target) //寻找右边界,在num[mid]大于target的时候,num[mid]就一定不是右边界
right=mid-1; //因此这里就给right赋值mid-1
else
left=mid+1;
}
int rightBoard=nums[right]==target?right:-1;