二分模板一共有两个,分别适用于不同情况。
算法思路:假设目标值在闭区间[l, r]中, 每次将区间长度缩小一半,当l = r时,我们就找到了目标值。
版本1
当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。
为什么此时l+r不加1,因为l的执行条件是l=mid+1。即使l=1,r=2,mid=1。l会在mid的基础上加1,从而跳出循环。
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
版本2
当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。
为什么此时l+r要加1,因为l执行的条件是l=mid。当l=1,r=2时,如果mid=(l+r)>>1,那么mid=1,此时l=mid仍要循环就死循环了。所以要向上加1。
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
别管下面
注意点:当left=1,right=2时如果用(left+right)/2,二分结果还是1.死循环。。
要用(left+right+1)/2。
class Solution {
public boolean isPerfectSquare(int num) {
long left=0;
long right=num;
while(left<right){
long mid=(left+right+1)/2; //注意
if(mid*mid<=num)
left=mid;
else if(mid*mid==num)
return true;
else
right=mid-1;
}
return left*left==num;
}
}