二分查找
自己写二分查找很容易写错边界,进入死循环,这里总结下模板,分为三种类型(假设数组a递增):
- 查找坐标i,使得a[i]=num,这个比较简单,不会陷入死循环:
while(left<right){
int middle = (left+right)/2;
if(a[middle]=num) ans=middle;
else if(a[middle]>num) right=middle-1;
else left=middle+1;
}
- 查找满足a[i]>=num的最小坐标i
while(left<right){
int middle = (left+right)/2;
if(a[middle]<num) left=middle+1;
else right=middle;
}
注意,死循环通常发生在left+1=right的情况,因此需要格外注意if-else中right=middle的情形。假设left=0,right=1,不论条件语句if-else走向哪个分支,都不会死循环。
3. 查找满足a[i]<=num的最大坐标i
while(left<right){
int middle = (left+right+1)/2;
if(a[middle]>num) right=middle-1;
else left=middle;
}
同理,假设left=0,right=1,如果middle采取上述的方案:middle=(left+right)/2=0,然后条件分支进入else语句,left=middle=0,则陷入了死循环。
总结
只需额外关注if-else中赋值为middle的分句,并在middle的赋值对应上取整或下取整,以避免陷入死循环。