zoukankan      html  css  js  c++  java
  • 二分

    定义:二分的基础用法是在单调序列或者单调函数中进行查找。
    根据复杂度理论,我们可以通过将求解改为判定的方法,优化算法。这是一种非常基础,又比较容易写错的算法。本文将阐述一种常见的二分方法。

    整数集合上的二分

    保证最终答案处于闭区间 $ [l,r] $ 以内,循环以 $ l == r $ 结束,每次二分的中间值会归属于左半段或者右半段。

    应用
    单调递增序列求 $ x $ 或 $ x $ 的后继:

    	while (l < r) {
    		mid = (l + r) / 2;
    		if (a[mid] >= x) r = mid;
    		else l = mid + 1;
    	}
    

    单调递增序列求 $ x $ 或 $ x $ 的前驱:

    	while (l < r) {
    		mid = (l + r + 1) / 2;
    		if (a[mid] <= x) l = mid;
    		else r = mid - 1;
    	}
    

    注意:可行解一定要在选取的区间之内,一定不能造成没有缩小可行区域的情况

    如上面两种代码所示,这种闭区间的二分有两种形式

    1. 缩小范围时,$ r = mid $, (l = mid + 1),取中间值时,(mid = (l + r) / 2)
    2. 缩小范围时,$ l = mid $, (r = mid - 1),取中间值时,(mid = (l + r + 1) / 2)

    思考一下,如果第二种情况仍然使用 (mid = (l + r) / 2), 如果 (r - l == 1) 那么 (mid) 的值就会和 (l) 一样,会造成没有缩小可行区域的情况,进入死循环
    仔细分析这两种 (mid) 的取值,我们还发现:(mid = (l + r) / 2) 不会取到 (r) 这个值,(mid = (l + r + 1) / 2) 不会取到 (l) 这个值。我们可以利用这一性质来处理无解的情况,即:把最初的二分区间 ([1,n]) 变成 ([0,n]) 或者 ([1, n+1]),如果最终结果在这两个不存在的值上,那就是没有答案。
    因此,使用配套(mid) 取法时必须的。

    至此,整数域的二分已经讲完,采用" (l = mid + 1, r = mid - 1) " 或 “ (l = mid, r = mid) "的代码形势也很常见,但是在这里不做过多的阐述

    实数域上的二分

    实数域上的二分比较简单,设置精度,然后直接二分就可以。

    while (l + eps < r) {
        double mid = (l + r) / 2;
        if (calc(mid)) r = mid; else l = mid;
    }
    
  • 相关阅读:
    mysql bin log配置及查看
    Java 相关书籍
    mysql查询性能优化
    Java线程并发:知识点
    Java 根据经纬度计算两点之间的距离
    Java加解密AES、DES、TripleDES、MD5、SHA
    Java类加载基本过程
    基本排序算法(冒泡排序 选择排序 插入排序 快速排序 归并排序 基数排序 希尔排序)
    Three.js 中的参数调试控制插件dat.GUI.JS
    Three.js中的动画实现02-[Three.js]-[Object3D属性.onAfterRender/.onBeforeRender]
  • 原文地址:https://www.cnblogs.com/Alessandro/p/9709649.html
Copyright © 2011-2022 走看看