二分查找
tips:
1.二分查找并不一定需要单调性
2.如果有单调性,一定可以二分,可以二分的不一定非有单调性
3.二分的本质是每一次循环需要选择答案所在的区间,即更新l, r两个坐标
整数二分
对于整数二分,有两种方法,分别适用于两个不同的情况,即想找到红色线的蓝圈还是绿色线的蓝圈
如果想找红色线的蓝圈,则check(mid)的标准在判断mid是否在黑线上
1 if(check(mid)) //满足黑线的性质,红线的蓝圈在[l, mid],否则红线的蓝圈在[mid + 1, r] 2 r = mid; 3 else 4 l = mid + 1
如果想找绿线的蓝圈,则check(mid)的标准在判断mid是否在粉线上
1 if(check(mid)) //满足粉线的性质,绿线的蓝圈在[mid, r],否则绿线的蓝圈在[l, mid - 1] 2 l = mid; 3 else 4 r = mid - 1
trick:
每次先写一个check(mid),然后考虑true的情况如何更新,如果更新方式是l = mid,则mid = l + r +1 >> 1
1.
1 mid = l+r+1 >>1 //要加1的原因:如果l = r -1,即l和r只差一个数,mid = l,为true的时候会死循环 2 if(check(mid)) [mid, r], l = mid 3 else [l, mid-1] r = mid-1
2.
1 mid = l+r >> 1 2 if(check(mid)) [l, mid], r = mid 3 else [mid+1, r] l = mid+1
浮点二分
对于浮点数二分,
1 while(r - l > 1e-8) 2 { 3 int mid = (l + r) / 2; 4 if(check(mid)) r = mid; 5 else l = mid; 6 }