二分
算法原理简单,特别需要注意边界细节!!
有单调性的问题一定可以二分,没单调性不一定不能二分。
思想:
1)首先要确定出一个区间。
满足:使得目标值一定在区间内。
2)找出一个性质即判断条件。
满足:①判断条件具有二段性(例:使得区间前连续一段满足此判断条件,后连续一段不满足此判断条件,中间无缝缺失部分)。
②目标值为二段性的分界点。
整数二分:
分为两种情况,情况①指目标值为前段最后一个值,情况②指目标值为后段的第一个值。
如下图所示:
情况①:ans是红区域右端点。
将[L,R]分为[L,M-1],[M,R]
if(M是红色的)说明ans在[M,R];
else (M是蓝色的)说明ans在[L,M-1];
对应代码:
while(L<R){
M=(L+R+1)/2;
if(M==红) L=M;//区间变成[M,R]
else R=M-1;//区间变成[L,M-1];
}
注:其中第三行L=M是需要特别注意的!!
当L=M时,对应的第二行必须是(L+R+1)/2;如果没有加1会进入死循环。
例:当区间只剩 下两个数的时候,第二行M=(L+R)/2执行完将会向下取整使得M=L,第三行执行完L=M相当于M没有改变!!!程序进入死循环。
情况②:ans是蓝区域左端点
将[L,R]分成[L,M],[M+1,R]
if(M是蓝色)说明ans在[L,M];
else (M是红色的)说明ans在[M+1,R];
对应代码:
while(L<R){
M=(L+R)/2;
if(M==蓝) R=M;//区间变成[L,M]
else L=M+1;//区间变成[M+1,R];
}
注:和情况①相似的是,其中第三行R=M是需要特别注意的!!
当R=M时,对应的第二行必须是(L+R)/2;如果有加1会进入死循环。
例:当区间只剩下两个数的时候,第二行M=(L+R+1)/2执行完将会向上取整使得M=R,第三行执行完R=M相当于M没有改变!!!程序同样进入死循环。
例题链接:
实数二分:
相比整数二分,实数二分的情况单一,不需要区分m-1或m+1。
具体解析:
将区间[L,R]划分成[L,M],[M,R]
if(M==红色)说明ans在M和R之间
else说明ans在L和M之间
代码:
while(R-L>1e-6){
double M=(L+R)/2;
if(M==红)L=M;
else R=m;
}
例题链接:...
.....