浅谈二分算法

news2024/12/26 0:15:36

浅谈二分算法

二分

首先知道一下二分是什么。

二分,是一种快速处理大型数据的方法。基本逻辑是折半查找。

设有一个共有 n n n 个数字的数组,要从中查询某个元素,就可以用二分查找。

注:这里的数组默认其成员数值具有单调性。这个点十分重要。

还记得小时候(我现在才新初一)跟同学玩过一个游戏(数字炸弹),当时玩得可欢了,一直以为是一个概率小游戏(其实确实有概率的成分),每局能玩上十几分钟。

但是现在学完信息学后,特别是学完二分后,对它有了一种快速解决的方法。

首先我们知道,设出题者所想的这个数字为 x x x,则 x ∈ [ 1 , 100 ] x\in[1,100] x[1,100],这是我们玩的规则,不过大差不差。

那么很显然,因为 1 ∼ 100 1\sim 100 1100 具有单调上升的性质,而我们又只需要查找一个数,暴力的求解方法是从 1 1 1 尝试到 100 100 100,最坏情况下需要枚举 100 100 100 次,十分漫长。

而我们可以想到,每次说出一个数 y y y,只要不是 y = x y=x y=x,就可以排除 100 − y + 1 100-y+1 100y+1 y y y​​ 个数(这取决于你猜的这个数是大了还是小了)。

那么我们就可以利用这个特性,假设共有 n n n 个数字,每次都排除 n ÷ 2 n\div2 n÷2 个数字,这样最多经过 log ⁡ 2 n \log_2^n log2n 次后就可以结束游戏。

其实小学课本里就有类似的例子,是数学书里一个单元叫做 “ 找次品 ” 的数学问题(不知道的自己查),但那里是用 log ⁡ 3 n \log _3^n log3n 的时间,这里不再赘述。

双指针

双指针,顾名思义,就是运用两个变量 l , r l,r l,r​ 表示所求区间的左右端点,可以更加轻松地控制对答案有贡献的区间。

设所求元素为 p p p,序列为 a a a

比如每次取个中点 m i d = ( l + r ) 2 mid=\frac{(l+r)}{2} mid=2(l+r),若 p < a m i d p<a_{mid} p<amid,则 r ← m i d r\leftarrow mid rmid,左端点 l l l 不变。将区间控制为 [ l , m i d ] [l,mid] [l,mid]

否则 l ← m i d + 1 l\leftarrow mid+1 lmid+1,将区间控制为 [ m i d + 1 , r ] [mid+1,r] [mid+1,r]

但这里问题就来了,区间为空的判定条件是 l = r l=r l=r 还是 l > r l>r l>r 呢?

二分查找的边界条件

枚举以下情况
  • 闭区间

若你用的是闭区间,即 [ l , r ] [l,r] [l,r],则判断条件即为 l = r l=r l=r,因为若 l = r l=r l=r,则 [ l , r ] [l,r] [l,r] 其实就是 [ l , l ] [l,l] [l,l] [ r , r ] [r,r] [r,r] ,就是一个数,答案也显然即为 a l a_l al​。

示意图:

  • 开区间

开区间,是 ( l , r ) (l,r) (l,r)不包括 l , r l,r l,r 。所以有效区间为 [ l + 1 , r − 1 ] [l+1,r-1] [l+1,r1]。判断条件即为 l + 1 = r − 1 l+1=r-1 l+1=r1​。

示意图:

  • 左开右闭

左开右闭,即 ( l , r ] (l,r] (l,r] 有效区间为 [ l + 1 , r ] [l+1,r] [l+1,r],边界条件即为 l + 1 = r l+1=r l+1=r​,还是就剩下一个数为止。

示意图:

  • 左闭右开

左闭右开 [ l , r ) [l,r) [l,r),有效区间为 [ l , r − 1 ] [l,r-1] [l,r1],边界条件为 l = r − 1 l=r-1 l=r1​。

示意图:

所以可以总结一下,不管你的 l , r l,r l,r 都表示什么意思,重点就是四个字,有效区间

大概大家也注意到了,我在解释除了闭区间其他情况的时候,有效区间的左右端点都是用闭区间来表示,为什么呢?当然是因为我个人喜欢用闭区间啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2076675.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++类和对象(总篇)

文章目录 C类和对象1、类的定义1.1类定义格式1.2访问限定符1.3类域 2、实例化2.1实例化概念 3、this指针4、类的默认成员函数5、构造函数5.1构造函数的特点5.2实例分析 6、析构函数6.1析构函数的特点6.2实例分析 7、拷贝构造函数7.1 拷贝构造函数的特点7.2实例分析7.3浅拷贝和深…

Linux中断管理

Linux 内核提供了完善的中断框架,我们只需要申请中断,然后注册中断处理函数即可,使用非常方便,不需要一系列复杂的寄存器配置。 1.Linux中断简介 中断号 每个中断都有一个中断号,通过中断号即可区分不同的中断,有的资料也把中断号叫做中断线。在 Linux 内核中使用一个 int 变…

神经网络—卷积层

1.讲解 Conv2d out_channels 参数为2时&#xff0c;会生成两个卷积核&#xff0c;分别与输入进行卷积。得到的两个输出为输出 新生成的卷积核和原来的卷积核不一定相同 in_channels (int) – Number of channels in the input image out_channels (int) – Number of channels…

Marching Cubes 算法再探

Marching Cubes 算法再探 基础过程代码mian.cppMarchingCubes.hMarchingCubes.cpp 之前做NeRF相关工作时简单看过&#xff0c;但没有深究其实现&#xff0c;知其然不知其所以然的程度&#xff0c;算是初探。 基础 为了对MC有大致了解&#xff0c;可以先根据Marching Cubes 算法…

两个实用的Python编程技巧

一、变量类型声明技巧 虽然在Python中可以不用声明变量的类型&#xff0c;但是为了加快程序的运算速度&#xff0c;减少不必要的bug&#xff0c;我们可以在定义变量之初就把它的类型确定&#xff0c;这样可以更好地传输变量值。如下面的例子。 我们定义了两个变量&#xff0c…

IO进程线程 240826作业

作业 创建3个进程,子进程1拷贝文件的前一半,子进程2拷贝后一半文件,父进程回收两个子进程资源。 将1.txt内容拷贝到2.txt中 #include <myhead.h> int main(int argc, const char *argv[]) {pid_t pid1;pid1 fork();int fd1 open("./1.txt",O_RDWR);if(fd1…

JavaWeb JavaScript ④ JS的对象和JSON

只要你的风格是适应客观规律的&#xff0c;那你以后会越来越好&#xff0c;做事情会越来越顺利 —— 24.8.26 一、JS创建对象 语法 方式1 new Object() 方式2 {属性名&#xff1a;属性值&#xff0c;… …&#xff0c;函数名&#xff1a;function(){}} 方式…

Python | Leetcode Python题解之第371题两整数之和

题目&#xff1a; 题解&#xff1a; MASK1 4294967296 # 2^32 MASK2 2147483648 # 2^31 MASK3 2147483647 # 2^31-1class Solution:def getSum(self, a: int, b: int) -> int:a % MASK1b % MASK1while b ! 0:carry ((a & b) << 1) % MASK1a (a ^ b) % MA…

Agent实际落地的应用 未来生活的无形助手

在这个信息爆炸的时代&#xff0c;我们每个人都在追求更高效的生活方式。想象一下&#xff0c;如果有一个无形的助手&#xff0c;能够理解我们的需求&#xff0c;自动处理繁琐的任务&#xff0c;甚至为我们提供个性化的建议&#xff0c;那将是多么美好的体验&#xff01;这正是…

线性DP经典题型

数字三角形&#x1f342; #include<bits/stdc.h> using namespace std; int main() {int n;cin>>n;vector<vector<int>>arr(n1,vector<int>(n1,0));for(int i 1;i<n;i){for(int j 1;j<i;j){cin>>arr[i][j];}}vector<vector<i…

【精选】分享9款AI毕业论文生成初稿题目网站

在当今学术研究领域&#xff0c;AI技术的应用日益广泛&#xff0c;尤其是在学术论文的撰写过程中。AI论文生成器的出现&#xff0c;极大地简化了学术写作流程&#xff0c;提高了写作效率。以下是9款推荐的AI毕业论文生成初稿的网站&#xff0c;它们各有特色&#xff0c;能够满足…

【Qt】多元素控件QTableWidget

多元素控件QTableWidget 使用QTableWidget表示一个表格控件&#xff0c;一个表格中包含若干行、每一个行又包含若干列。 表格中的每一个单元格&#xff0c;都是一个QTableWidget对象。 QTableWidget核心方法 方法说明 item(int row, int column) 根据⾏数列数获取指定的 Q…

【电路笔记】-运算放大器基础

运算放大器基础 文章目录 运算放大器基础1、概述2、运算放大器表示3、开环增益(Open-Loop Gain)4、输入和输出阻抗5、带宽6、偏移电压7、理想运算放大器模型7.1 饱和模式7.2 线性模式8、实际运算放大器9、总结1、概述 本文将介绍运算放大器(也称为运算放大器,Operational …

HandBrakeCLI 压缩工具的简单实用

HandBrakeCLI -i input.mp4 -o output.mp4 --encoder qsv_h264 -b 500k --preset "Android 576p25" --width 320 --height 576 --quiet--encoder qsv_h264 意思代表inter的gpu编码 -b 500k 设置比特率 --preset "Android 576p25" 设置预设 --width 320 --…

揭秘OTP与MTP:你的存储小秘密,一次性和多次可编程大不同!

NVM,即非易失性存储器,是一种非易失性内存。 NVM的特点是存储的数据在断电后不会消失。传统的NVM,如掩模ROM、可编程ROM(PROM)、可擦除可编程ROM(EPROM)、电可擦可编程ROM(EEPROM)、NAND/NOR闪存等,以及目前正在开发的许多新型状态存储器,如磁性存储器(MRAM)、电…

Jar包导入本地maven仓库

当jar包未引入到公共maven仓库时&#xff0c;直接通过maven坐标的方式引入会报错&#xff0c;找不到该依赖。所以可以将jar包导入到本地maven仓库&#xff0c;再通过maven坐标引入后就没有问题。 mvn install:install-file -Dfilexxxxxx.jar -DgroupIdcom.xx -DartifactIdxxxx…

idea debug 各个步骤含义

基本功能 IntelliJ IDEA 的 Debug 功能提供了强大的调试支持&#xff0c;允许开发者逐步执行代码&#xff0c;检查变量值&#xff0c;评估表达式等。以下是 Debug 模式中常见的几个按钮及其含义&#xff1a; Show Execution Point (显示执行点)&#xff1a;将光标跳转到当前正在…

如何使用ssm实现模具制造企业订单跟踪管理系统+vue

TOC ssm256模具制造企业订单跟踪管理系统vue 绪论 1.1 研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;…

编程仙尊——深入理解指针(1)

目录 1.认识指针 2.指针变量和地址 2.1取地址操作符&#xff08;&&#xff09; 2.2 指针变量和解引用操作符 2.3 指针变量的大小 3.指针类型的意义 3.1指针的解引用 3.2 指针-整数 3.3 void*指针 1、认识指针 在生活中&#xff0c;一栋楼的每个房间都会有房间号 …

OpenGL实现3D游戏编程【连载5】——纹理坐标、纹理贴图

OpenGL实现3D游戏编程【连载5】——纹理坐标、纹理贴图 欢迎来到zhooyu的专栏。 个人主页&#xff1a;【zhooyu】 文章专栏&#xff1a;【OpenGL实现3D游戏编程】 本专栏内容&#xff1a; 我们从游戏的角度出发&#xff0c;用C去了解一下游戏中的功能都是怎么实现的。这一切还…