二分搜索法简单分析与总结(转)
来源:互联网 发布:注册淘宝也是支付宝 编辑:程序博客网 时间:2024/06/06 01:08
二分搜索法简单分析与总结( 转载)
原文链接(感谢题主):
http://zhengboyang.com/2016/03/18/%E4%BA%8C%E5%88%86%E6%90%9C%E7%B4%A2%E6%B3%95%E7%AE%80%E5%8D%95%E5%88%86%E6%9E%90%E4%B8%8E%E6%80%BB%E7%BB%93/
二分搜索法,是通过不断缩小解可能存在的范围,从而求得问题最优解的方法。在程序设计竞赛特别是ACM中,经常可以见到二分搜索法和其他算法结合的题目。
本文主要总结了二分的几种常用写法。
——————————————————————————————————————————
lower_bound
给定长度为 nn 的单调不下降数列 a0,a1,…,an−1a0,a1,…,an−1 和一个数 kk,求满足 ai≥kai≥k 条件的最小的 ii。不存在的情况下输出 nn。
满足“二分值越大越容易满足条件”,等同于“最小化最大值”,参见下方描述。
——————————————————————————————————————————
upper_bound
给定长度为 nn 的单调不下降数列 a0,a1,…,an−1a0,a1,…,an−1 和一个数 kk,求满足 ai>kai>k 条件的最小的 ii。不存在的情况下输出 nn。
满足“二分值越大越容易满足条件”,等同于“最小化最大值”,参见下方描述。
——————————————————————————————————————
最大化最小值
此种题目一般是“二分值越小越容易满足条件”,然后求符合条件的最大值。
区间长度为1时的写法:
解的范围为 [lb,rb][lb,rb]。
1
2
3
4
5
6
7
8
9
// 计算区间为[lb, rb]
while( rb > lb ) // 区间长度为1时终止循环
{
// 防止溢出
int m = lb + (rb - lb + 1) / 2; // 由于是区间长度为1时终止循环,所以要加1
if( ok(m) ) lb = m;
else rb = m - 1;
}
// 跳出循环时 lb == rb
区间长度为2时的写法:
解的范围为 [lb,rb)[lb,rb)。
1
2
3
4
5
6
7
8
9
while( rb - lb > 1 ) // 区间长度为2时终止循环
{
// 防止溢出
int m = lb + (rb - lb) / 2; // 由于是区间长度为2时终止循环,所以不用加1(不会死循环)
if( ok(m) ) lb = m;
else rb = m;
}
// 跳出循环时 lb + 1 == rb
// 答案为 lb
最小化最大值
此种题目一般是“二分值越大越容易满足条件”,然后求符合条件的最小值。
区间长度为1时的写法:
解的范围为 [lb,rb][lb,rb]。12345678while( rb > lb ){ // 防止溢出 int m = lb + (rb - lb) / 2; // 这里虽然区间长度为1,但不需要加1(不会死循环) if( ok(m) ) rb = m; else lb = m + 1;}// 跳出循环时 lb == rb区间长度为2时的写法:解的范围为 (lb,rb](lb,rb]。123456789while( rb - lb > 1 ){ // 防止溢出 int m = lb + (rb - lb) / 2; if( ok(m) ) rb = m; else lb = m;}// 跳出循环时 lb + 1 == rb// 答案为 rb浮点数的二分浮点数二分一般直接指定循环次数(100次)作为终止条件。1次循环可以把区间的范围缩小一半,100次的循环则可以达到 2−100≈10−302−100≈10−30 的精度范围,基本上是没有问题的。123456for( int i = 0; i < 100; ++ i ){ double m = (lb + rb) / 2; ...}// 跳出循环时 lb 与 rb 近似相等,所以都可作为答案
此外,也可以类比整数的二分,把终止条件设为像 (r−l)/2>EPS(r−l)/2>EPS,依然通过指定一个区间的大小来终止循环。但是,如果 EPSEPS 取得太小了,就有可能因为浮点小数精度的原因导致陷入死循环。因此,对于浮点数,一般还是建议通过指定循环次数来作为终止条件。
总结
其实重点还是 最大化最小值 和 最小化最大值 的区分。可以发现:
对于区间长度为1的写法,两者的解存在范围都是闭区间。即初始化时 lblb 作为解的最小值,rbrb 作为解的最大值就可以了。唯一不同的是,求 最大化最小值 时,中间值的计算需要加1再除以2。这是这种写法的一个特征,可以自己手动验算下区间长度为1时是否能跳出循环。
对于区间长度为2的写法,两者的解存在范围都是半开半闭区间。即初始化时,有一边(左/右)需要加1或减1(以保证能求到解的最值)。答案也不同,一个是左值,一个是右值。
写法记一种就够了,记多了反而容易混淆。当然,归根结底,还是要多做题,多思考…
- 二分搜索法简单分析与总结(转)
- 【算法设计与分析】3、二分搜索
- 二分查找法与二分搜索树
- 二分(二分答案、二分搜索)与单调性
- 二分搜索简单实现(binanry search)
- 简单算法--二分搜索
- 二分搜索总结
- 二分搜索总结
- 二分搜索的总结
- 总结一下二分搜索
- 二分和三分总结与误区分析
- 005-二分搜索-分治法-《算法设计技巧与分析》M.H.A学习笔记
- java-算法设计与分析之二分搜索
- 算法分析与设计-03-二分搜索算法
- 二分搜索与一般搜索
- 简单的二分搜索算法
- 最最简单的二分搜索
- 二分搜索的总结(续)
- hdu 变形课(DFS)
- 调用相机拍照,处理图片旋转,保存图片
- Struts 关于validator的regex验证
- ios 导航栏,标签栏,工具栏和状态栏
- 在屏幕中实现自动输入文本效果
- 二分搜索法简单分析与总结(转)
- nyoj 1027 防守阵地 <思维>
- java 队列和二叉树代码
- 上传本地代码到github上
- cudaDeviceReset
- linux 操作系统中ping测试网络连通性命令的使用
- android面试专题(9)
- HOJ 1002题 题解
- 开通博客啦