二分答案
二分答案,就是用二分的方法,在可能的答案区间里找出问题的答案,大多数情况下用于求解满足某种条件下的最大(小)值,前提是答案具有单调性,同时也可以理解为是一种倒推方法(先找答案在判断答案是否可行、有没有更优解)。
二分答案的主要思想
• 在答案的可能范围(区间)内二分枚举
• 并检查所穷举的答案是否符合题意
• 将最优性问题(直接求解相对较难)
• 转化为可行性问题(答案是否符合题意相对容易)
二分答案有两种情况:
下图中L,R为当前答案区间,M为中心点,根据二分思想判断M是否符合条件,再移动L或R,变成L’,R’,图中的T和F表示是否符合条件。
1.最小值最大化
int l = min_ans, r = max_ans;
while (l < r) {
int mid = (l + r + 1) / 2; //+1避免 r == l + 1 时mid一直等于l,从而死循环
if (OK(mid)) //符合条件返回True
l = mid;
else
r = mid - 1;
}
希望答案尽可能大,所以我们需要确保左区间L点符合题目条件(最小),至于R是否符合条件是不确定的,首先判断M点符合与否,符合则将L移到M点,维持了L的True属性,也增大了所要的最小值所在区间,如果不符合,没办法在保持L的True属性情况下移动L,那就移动R。
2.最大值最小化
int l = min_ans, r = max_ans;
while (l < r) {
int mid = (l + r) / 2;
if (ok(mid)) //符合条件返回True
r = mid;
else
l = mid + 1;
}
按同样道理分析,维持R的True属性即可。这里的mid就不需要加1了,因为 mid 跟 l 重合时,l = mid + 1;会自增,而当 mid 和 r 重合时 l 也跟 r 重合,结束循环了。
注意点
- 每次循环都要确保L和R有一个被更新,否则就会出现死循环
- 答案是浮点数的情况:区间更新不能加1,这样变动太大,直接进行以下操作:
l = mid;
r = mid;