二分查找及二分答案

2023-11-15

一、二分思想

二分是一种常用且非常精妙的算法,常常是我们解答问题的突破口,二分的基本用途是在单调序列或单调函数中做查找操作,因此当问题的答案具有单调性时,就可以通过二分把求解转化为判定(根据复杂度理论,可知判定的难度小于求解),这使得二分的应用范围变得很广泛。

二分的关键是边界,而不是单调性,所以,小白学习二分一定要注意边界问题。

二、二分查找

线性查找需要从头开始不断地按顺序检查数据,因此在数据量大且目标数据靠后,或者目标数据不存在时,比较的次数就会更多,也更为耗时。若数据量为 n,线性查找的时间复杂度便为 O(n)。

二分查找只能查找已经排好序的数据。二分查找通过比较数组中间的数据与目标数据的大小,可以得知目标数据是在数组的左边还是右边。因此,比较一次就可以把查找范围缩小一半。重复执行该操作就可以找到目标数据,或得出目标数据不存在的结论。

下面看图说话

 因为每次都可以将区间大小缩小一半,所以最多只需要 log(n) 次就可完成查 找,所以二分查找的复杂度是 O(log(n)) 

二(1)整数二分查找模版

int find(int x)
{
	int l = 1;
	int r=n+1;//左闭右开的区间哦
	while(l<r)
	{
		int mid = (l+r)/2;//l+(r-l)>>1这样可以避免越界
		if(a[mid]>=x)
			r=mid;
		else l=mid+1;
	}
	if(a[l]==x) return 1;
	else return -1;
}

二(2)实数域二分

int Erfen( double l, double r)
{∥dlt=0.001(根据题目要求决定精度)
double mid;
while(fabs(l-r)>dlt)
{
mid=(l+r)/2.0;
if( check(mid))r=mid;
else l=mid;
}
return l;
};

如上所述,如果我们指定二分的次数t,那么对于初始的求解区间长度L,算法结束后r-1的值会是L/2^t,根据这个值判断精度是否达到我们的要求即可 。

二(3)STL中的二分查找

1、upper_bound  

upper_bound(begin,end,num)会从数组的begin 位置到end−1 位置二分查找第一个大于 num的数字的位置(最终返回的是一个地址,即第一个大于num的数字的位置,如果不存在则返回-1。通过返回的地址减去起始地址 ,得到找到数字在数组中的下标。)

#include<bits/stdc++.h>

using namespace std;

int main(){  

int num[6]={1,2,4,7,15,34};

sort(num, num + 6); //按从小到大排序

int pos = upper_bound(num, num + 6, 7) - num; //返回数组中第一个大于或等于被查数的值

cout << pos << " " << num[pos] << endl;

return 0;

}

输出:4 15

2、lower_bound

lower_bound(begin,end,num) 会从数组的begin 位置到end-1 位置二分查找第一个大于或等于num的数字的位置

#include<bits/stdc++.h>

using namespace std;

int main(){

int num[6] = {1, 2, 4, 7, 15, 34};

sort(num, num + 6); //按从小到大排序  

int pos = lower_bound(num, num + 6, 7) - num; //返回数组中第一个大于或等于被查数的值

cout << pos << " " << num[pos] << endl;

return 0;

}

输出结果:3 7

三、二分答案

当问题的答案具有单调性时,就可以通过二分把求解转化为判定(根据复杂度理论,可知判定的难度小于求解)

第一种写法:左闭右开区间写法:[l,r),循环l=r结束

每次二分的中间值mid会归属于左半段与右半段二者之一。

  1. 在单调递增序列a中查找>=x的数中最小的一个(即x或x的后继):
    while(l<r)
    {
    int  mid = (l+r)>>1;//mid=l+(r-l)/2;//>>向下取整,整除是向零取整
    if(check(mid)) r=mid;//a[mid]>=x
    else l=mid+1;
    }
    return a[l];
  • 在单调递增序列a中查找<=x的数中最大的一个(即x或x的前驱):
    while(l<r)
    {
    int  mid = (l+r+1)>>1;
    if(check(mid)) l=mid;//a[mid]<=x
    else r=mid-1;
    }
    return a[l];

    为什么需要+1?
    原因是如果不加上1,那么mid得到的是下取整的数,那么有可能[mid,r]更新过后mid会一直等于mid(mid==r的情况)会陷入死循环左闭右闭的写法,[l,r]

  • 第二种写法,[l,r]写法

  • 最小值最大(或是最大值最小)问题,这类双最值问题常常选用二分法求解,也就是确定答案后,配合贪心、DP等其他算法检验这个答案是否合理,将最优化问题转换为判定性问题。

当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。  

        当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。 

例题讲解: 

 例1:查找

例2:眼红的Medusa

例3: 击进的奶牛

例4:数列分段

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

二分查找及二分答案 的相关文章

  • 从多线程程序中调用 system()

    我们正在开发一个用 C 编写的多线程内存消耗应用程序 我们必须执行大量的 shellscript linux 命令 并获取返回码 读完之后article http www linuxprogrammingblog com threads a
  • SSL/TLS/HTTPS 站点在 C#/.NET WebBrowser 控件中非常慢,但在 Internet Explorer 中则很好

    背景 我正在修改自动维基浏览器 http en wikipedia org wiki Wikipedia AutoWikiBrowser使用托管在安全服务器上的 MediaWiki 站点 我允许用户通过 C 应用程序中的 WebBrowse
  • C# 正则表达式用于查找 中具有特定结尾的链接

    我需要一个正则表达式模式来查找字符串 带有 HTML 代码 中的链接 以获取文件结尾如 gif 或 png 的链接 示例字符串 a href site com folder picture png target blank picture
  • 如何创建用于 QML 的通用对象模型?

    我想知道是否有任何宏或方法如何将 Qt 模型注册为 QObject 的属性 例如 我有AnimalModel http doc qt io qt 5 qtquick modelviewsdata cppmodels html qabstra
  • 将字符串转换为正确的 URI 格式?

    有没有简单的方法可以将电子邮件地址字符串转换为正确的 URI 格式 Input http mywebsite com validate email 3DE4ED727750215D957F8A1E4B117C38E7250C33 email
  • 如何生成 appsettings..json 文件?

    我有一个 ASP NET Core 2 WebAPI 它将部署在以下环境中 INT QA STAGE 生产环境 基于上述 我需要有appsettings
  • 如何将带有自定义分配器的 std::vector 传递给需要带有 std::allocator 的函数?

    我正在使用外部库 pcl 因此我需要一个不会更改现有函数原型的解决方案 我正在使用的一个函数生成一个std vector
  • 劫持系统调用

    我正在编写一个内核模块 我需要劫持 包装一些系统调用 我正在暴力破解 sys call table 地址 并使用 cr0 来禁用 启用页面保护 到目前为止一切顺利 一旦完成 我将公开整个代码 因此如果有人愿意 我可以更新这个问题 无论如何
  • 对 boost 库的依赖项没有完整路径

    我已经成功构建了动态库 依赖于使用自定义前缀构建和安装的 boost 库 b2 install prefix PREFIX 然而 当我跑步时otool L在我的库中 我得到如下输出 libboost regex dylib compatib
  • 从 Code::Blocks 运行程序时出现空白控制台窗口 [重复]

    这个问题在这里已经有答案了 当我尝试在 Code Blocks 中构建并运行新程序时 控制台窗口弹出空白 我必须单击退出按钮才能停止它 它对我尝试过的任何新项目 包括 Hello world 都执行此操作 奇怪的是 它对于我拥有的任何旧项目
  • 2D morton 码编码/解码 64 位

    如何将给定 x y 的莫顿代码 z 顺序 编码 解码为 32 位无符号整数 生成 64 位莫顿代码 反之亦然 我确实有 xy2d 和 d2xy 但仅适用于 16 位宽的坐标 产生 32 位莫顿数 在网上查了很多 但没有找到 请帮忙 如果您可
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • C++11 动态线程池

    最近 我一直在尝试寻找一个用于线程并发任务的库 理想情况下 是一个在线程上调用函数的简单接口 任何时候都有 n 个线程 有些线程比其他线程完成得更快 并且到达的时间不同 首先我尝试了 Rx 它在 C 中非常棒 我还研究了 Blocks 和
  • 从 R 到 C 处理列表并访问它

    我想使用从 R 获得的 C 列表 我意识到这个问题与此非常相似 使用 call 在 R 和 C 之间传递数据帧 https stackoverflow com questions 6658168 passing a data frame f
  • asp.net网格分页的SQL查询

    我在用iBatis and SQLServer 使用偏移量和限制进行分页查询的最佳方法是什么 也许我添加该列ROW NUMBER OVER ORDER BY Id AS RowNum 但这只会阻止简单查询的数据访问 在某些情况下 我使用选择
  • Visual Studio 2017 完全支持 C99 吗?

    Visual Studio 的最新版本改进了对 C99 的支持 最新版本VS2017现在支持所有C99吗 如果没有 C99 还缺少哪些功能 No https learn microsoft com en us cpp visual cpp
  • C语言声明数组没有初始大小

    编写一个程序来操纵温度详细信息 如下所示 输入要计算的天数 主功能 输入摄氏度温度 输入功能 将温度从摄氏度转换为华氏度 独立功能 查找华氏度的平均温度 我怎样才能在没有数组初始大小的情况下制作这个程序 include
  • 以 UTF8 而不是 UTF16 输出 DataTable XML

    我有一个 DataTable 我正在使用 WriteXML 创建一个 XML 文件 尽管我在以 UTF 16 编码导出它时遇到问题 并且似乎没有明显的方法来更改它 我了解 NET 在字符串内部使用 UTF 16 这是正确的吗 然后 我通过
  • 服务器响应 PASV 命令返回的地址与建立 FTP 连接的地址不同

    System Net WebException 服务器响应 PASV 命令返回的地址与建立 FTP 连接的地址不同 在 System Net FtpWebRequest CheckError 在 System Net FtpWebReque
  • 如何使用 C# 以低分辨率形式提供高分辨率图像

    尝试使用 300dpi tif 图像在网络上显示 目前 当用户上传图像时 我正在动态创建缩略图 如果创建的页面引用宽度为 500x500px 的高分辨率图像 我可以使用相同的功能即时转换为 gif jpg 吗 将创建的 jpg 的即将分辨率

随机推荐

  • 点云检测笔记2022

    目录 激光雷达综述 2022以前的点云检测 自动驾驶中的坐标系 Complex YOLOv4 激光雷达综述 百度安全验证
  • 记公司同事的一次集体活动

    花田游记 李维俊 杭州大区 风和日丽暖 春意现昂然 花田一日游 同事尽相伴 借着浓浓的春意在3月26日杭州大区组织到海上花田烧烤游玩 告别了城市的喧嚣 没有了工作的压力围绕在我们身边的只有体现同事之间紧密团队精神的欢声笑语 上午我们团队一行
  • Python优雅的日志——loguru

    loguru RECOMMENDATION 影视 loguru 据小提莫观察 在python的使用者中 善于聪明 偷懒 以及不重复造轮子已经成为大家的共识 正所谓 人生苦短 我用python 作为python的爱好者 肯定是喜欢python
  • 【分析】segments的version_map_memory指标具体表示什么?

    ES有很多的监控指标 其中有一些指标官方解释的实在模糊 比如version map memory byte units Total amount of memory used by all version maps across all s
  • JAVA 集合之迭代器Iterator

    Java语言中的Iterator功能比较简单 只能单向移动 它的主要功能有四种 1 凡是实现Collections接口的数据结构都可以使用该方法 第一次调用Iterator的next 方法时 它返回序列的第一个元素 2 使用next 获得序
  • 前哈工大教授开发的ChatALL火了!可同时提问17个聊天模型,ChatGPT/Bing/Bard/文心/讯飞都OK...

    丰色 发自 凹非寺量子位 公众号 QbitAI 今天的你 是否还在几个聊天大模型之间 反复横跳 毕竟各家训练数据和方法不尽相同 擅长和不擅长的东西也都不一样 现在 不用这么麻烦了 有人开发了一个名叫 ChatALL 的应用 可以将你的提问同
  • CTFShow Web7&Web8

    这两道题都是版本控制工具直接部署到生产环境中造成的信息泄露 所以在此一起总结 题目中给出了明显的提示 版本控制很重要 但不要部署到生产环境更重要 和备份文件泄露的题型一样 笔者自己的感觉是这种题型最常用的工具就是dirsearch 因此选择
  • C++类的默认成员函数 —— 析构函数

    一 概念 析构函数 与构造函数功能相反 析构函数不是完成对对象本身的销毁 局部对象销毁工作是由编译器完成的 而对象在销毁时会自动调用析构函数 完成对象中资源的清理工作 二 特征 析构函数是特殊的成员函数 其特征如下 1 析构函数名是在类名前
  • 物联网、区块链、元宇宙和虚拟数字人离普罗大众有多远?

    首先 我们最早理解的数字人就是数字虚拟的一个假人 可能看起来很像二次元玩偶的样子 今天我觉得数字人是一种虚拟的数字身份 无所谓你的形象是仿真或是任何形象 包括你在现实中无法实现的形象 你在梦想中所渴望的概念 无论它是什么样的 它是你在另外一
  • 微信小程序,计算时分秒时间差

    shijiancha function faultDate completeTime var stime Date parse new Date faultDate var etime Date parse new Date complet
  • r语言(总)(我命油我不油天)

    seq等间隔函数 seq from to by length out along with from to 为数值 表示开始和结束 by为数值 表示间隔 length out为数值 表示数列长度 along with为向量 表示数列长度与该
  • fabric基本概念

    Hyperledger fabric基本概念 首先fabric是由IBM贡献的超级账本框架 它是一个利用现有成熟的技术来组合而成的一个区块链技术的实现 它是一种允许可插拔实现各种功能的的模块化架构 它具有强大的容器技术 来承载各种主流语言来
  • C语言进阶——文件管理

    每当我们写好一段代码运行结束之后 再次运行的时候就会发现 之前在终端上输入的数据都会消失 那么如何把之前输入的数据保存下来呢 我们一般把数据持久化的方式有把数据存放在磁盘文件中 存放到数据库 打印等方式进行保存 使用文件我们可以直接将数据保
  • Mysql字符串处理函数详细介绍、总结

    1 ASCII str 返回字符的 ASCII 码值 返回值为字符串str 的最左字符 第一个字符 的数值 即取得最左字符的 ascii 码 假如str 为空字符串 则返回值为 0 假如 str 为 NULL 则返回值为 NULL ASCI
  • unity 不显示UI项,代码无法引用UI类

    如果在unity项目中遇到在Hierarchy面板右键发现没有ui这个选项 在vs里无法引用到UI类时可以进行以下操作 1 可以在unity的Project面板 选中Assets文件夹 右键选择 show in Explorer选项 开打资
  • vue3.0 新的api属性

    vue3 0 只需要升级vuecli4 0以上的版本就可以选择性的安装了 获取路由对象 import useRouter from vue router const router useRouter router push 即可调用路由跳转
  • 【转载】国内主要的量化交易平台及链接

    Bigquant 掘金 优矿 万矿 聚宽 米筐 真格 镭矿 量化云 点宽等 附 网站网址 Bigquant https bigquant com 掘金 https www myquant cn 优矿 https uqer io v3 com
  • java基础 基本包装类 System Math Array BigInteger BigDecimal

    基本类型包装类 1 1 基本类型包装类概述 在实际程序使用中 程序界面上用户输入的数据都是以字符串类型进行存储的 而程序开发中 我们需要把字符串数据 根据需求转换成指定的基本数据类型 如年龄需要转换成int类型 考试成绩需要转换成doubl
  • 面试题 08.08. 有重复字符串的排列组合--回溯算法

    LeetCode 面试题 08 08 有重复字符串的排列组合 有重复字符串的排列组合 编写一种方法 计算某字符串的所有排列组合 示例1 输入 S qqe 输出 eqq qeq qqe 示例2 输入 S ab 输出 ab ba 解法 回溯法
  • 二分查找及二分答案

    一 二分思想 二分是一种常用且非常精妙的算法 常常是我们解答问题的突破口 二分的基本用途是在单调序列或单调函数中做查找操作 因此当问题的答案具有单调性时 就可以通过二分把求解转化为判定 根据复杂度理论 可知判定的难度小于求解 这使得二分的应