首页 > 其他分享 >二分法

二分法

时间:2023-05-14 23:33:15浏览次数:32  
标签:right mid 二分法 while 端点 区间 left

本质

在有序区间内,找到一个分界线,分界线左侧元素均不满足某一个性质,右侧则相反。
极端情况下,左边和右边都可能为空。
可以按照具体定义将分界线归属为左边或者右边。

比如,上面的分界线 0 左侧都不大于 0,右侧都大于 0

先决条件

  1. 区间内元素有序;
  2. 区间左右端点确定。

题目特点

求某个最优解——比如,最小值最大、最大值最小。
最优解也就是分界线,左半边的右边界或者右半边的左边界。
比如,方程式求根,本质就是求区间内求满足 \(f(x)\leqslant 0\) 的 \(f(x)\) 的最小值(也就是 \(0\)) 对应的 \(x\);或者,像是如何使得玩家受到的伤害最小。

题目模板

  1. 定义左右端点
  2. 是否已经找到目标边界线(目标元素)——左右端点表示的区间只有一个元素时
  3. 计算中间点
  4. 判断中间点是否满足条件——while(condition)
    4.1 如果满足尝试在中间点左侧进行查找——将当前中间点作为右端点。
    4.2 否则,在中间点右侧进行查找——将当前中间点作为左端点。
    4.3 回到 2
left = ...;
right = ...;

while (left < right)
{
    mid = ...;
    if (pred(mid))
    {
      right = mid;
    }
    else
    {
      left = mid;
    }

}

开区间和闭区间

开区间对应 [left, right),这时候右端点不可能是目标边界线。所以为了确保区间不为空,必须满足 while(left < right),我们为了确保循环结束后区间对应一个元素应该将 while 中的条件设置为 left + 1 < right,这样循环结束时就会满足 left + 1 = right 的条件了。

闭区间对应 [left, right],右端点也可能是目标边界线。所以为了确保区间不为空,必须满足 while(left <= right),我们为了确保循环结束后区间对应一个元素应该将 while 中的条件设置为 left < right,这样循环结束时就会满足 left = right 的条件了。

中间点 mid 的计算

如果区间内只包含两个元素时,中间点 mid 会等于左端点或者右端点。
为了避免的死循环的问题,我们需要确保每次循环之后,区间范围都会减少——也就是左右端点中的某一个都会向中间移动一些。这时候,如果 mid 会等于左端点或者右端点,我们再让这个端点等于 mid,就会使用区间范围永远不变——陷入了死循环。这时候,我们应该让 left = mid + 1 或者 right = mid - 1

左右端点的更新方法和 mid 计算方法的对应关系如下。

mid = (left + right) / 2; // mid 靠左, 注意溢出的问题
left = mid + 1;
right = mid;
mid = (left + right + 1) / 2; // mid 靠右, 注意溢出的问题
left = mid;
right = mid - 1;

防止加法溢出的技巧

可以将

mid = (left + right) / 2;

替换为

mid = left + (right - left)/2;

或者将

mid = (left + right + 1) / 2;

替换成

mid = left + (right - left)/2 + ((left ^ right) & 1); // left 和 right 为一奇一偶时,需要 + 1

标签:right,mid,二分法,while,端点,区间,left
From: https://www.cnblogs.com/revc/p/17400417.html

相关文章

  • 1241.二分法求函数零点 | 浮点二分
    1241二分法求函数的零点题目来源信息学奥赛一本通题目描述\(有函数:f(x)=x5−15x4+85x3−225x2+274x−121.已知f(1.5)>0,f(2.4)<0且方程f(x)=0在区间[1.5,2.4]有且只有一个根,请用二分法求出该根。\)输出要求\(该方程在区间[1.5,2.4]中的根。要求四舍五入到小数点后6位。\)......
  • 查找(1.顺序查找、2.二分法查找)
    顺序查找既是for循环,在循环内用if匹配输入的值是否有对等,有即返回对应结果如果for循环下,没有对应的匹配值,要返回提示没找到用如下方法二分法查找1.必须是一个有序的列表2.先找到数组的中间值,拿输入值与其配对3.如果值是小了往左边选中间值,再匹对。反之向右.........
  • 二分法查找子序列
    判断子序列二分思路主要是对t进行预处理,用一个字典index将每个字符出现的索引位置按顺序存储下来intm=s.length(),n=t.length();vector<vector<int>>index(256,vector<int>());//先记下t中每个字符出现的位置for(inti=0;i<n;i++){charc=t[i];......
  • 分巧克力(二分法)
    题目描述儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有N块巧克力,其中第i块是Hi×Wi的方格组成的长方形。为了公平起见,小明需要从这N块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:形状是正方形,边长是整数;......
  • 二分法
    关于二分法:二分法使用要求待查找的数据集必须有序二分法的缺陷针对开头结尾的数据查找效率很低常见算法的原理以及伪代码二分法、冒泡、快拍、插入、堆排、桶排、数......
  • 算法—二分法详解
    二分法详解目录二分法详解1.二分法2.引论:猜数游戏3.整数域二分1、在单调递增序列中找x或者x的后继2、在单调递增序列中查找x或者x的前驱3.简易二分模板4.浮点数二......
  • python实现一个二分法
    #################      ############################### ......
  • 二分法:区间的重要性(初探)
    哈喽,我是404,正在努力提升代码能力的未来女程序员(笑),这是我的第一篇博客,接下来会记录我的学习之路到我力扣完全可以手撕,废话不多说,正文开搞!通过初见力扣经典题目704.二......
  • python实现一个二分法
    #################                 ############################### #########################......
  • 二分法求三次方根
      #include<iostream>usingnamespacestd;intmain(){doublen;cin>>n;intl=1,r=n;while(l+1e-7<r){doublemid=(l+r)/2;if(mid*mid*mid>=n){r=mid;}elsel......