不需要考虑mid+1、mid-1的二分查找模板,希望大家都能学会

news2024/9/27 19:17:39

文章目录

  • 一、模板示范
  • 二、模板
  • 三、细节说明
    • 为什么L的初始值为-1,R的初始值为N
    • 为什么循环结束的条件是while(L+1!=R)?
    • 不会陷入死循环
  • 最后
  • 四、
    •     例题one[数的范围](https://www.acwing.com/problem/content/791/)
    •     例题two[数的三次方根](https://www.acwing.com/problem/content/792/)
  • 五、相关学习的视频链接-[为啥二分查找容易出错](https://www.bilibili.com/video/BV1d54y1q7k7?spm_id_from=333.337.search-card.all.click)

一、模板示范

    闫而总之,只要所要寻找的数组能够满足某一条件而被分成两边,就能进行二分,这边我们就拿有序数组的二分来做例子;
    假设目前有这么一组数据:1 2 2 3 3 4 下标从0开始

在这里插入图片描述
    假设此时的情景为,需要我们找到第一个>=3的数字,试想一下,如果能把整个区间分了两半,左边是<3的区间,右边是>=3的区间 如图:

在这里插入图片描述
   那么右区间的第一个点,就是我们找到的符合>=3的第一个数字,将区间分为两半,是不是非常清晰!
   我先给出代码实现(不要害怕 马上就能见证奇迹)

#include<iostream>
using namespace std;
int main()
{
int a[6]={1,2,2,3,3,4};
int l=-1,r=6;//定义两个指针
while(l+1!=r)
{
	int mid=l+r>>1;//(相当于(l+r)/2)
	if(a[mid]<3) l=mid;//或者if(a[mid]>=3) r=mid;
	else r=mid;		   //	 else l=mid;
}
cout<<"第一个3所在的下标为  "<<r<<endl;
return 0;
}	
返回的结果为:第一个3所在的下标为  3

最后二分的结果就是下面这个图,是我们想要的样子!
然后因为我们要找到的是第一个>=3的数字,所以就取 r 也就是>=3区间的第一个数字;
在这里插入图片描述

二、模板

对于一个有序数组,假设下标为0,1,2,3…,n-1;总共n个数字
那么模板为

int L=-1,R=n;
while(L+1!=R)
{
	int mid=L+R>>1;
	if(check()) L=mid;
	else R=mid;
	//最后根据你所分左右两边区间的结果
	//选取L或者R作为结果
}

三、细节说明

为什么L的初始值为-1,R的初始值为N

   首先,如果二分本来就没有结果
比如对于本文例题 1 2 2 3 3 4,,如果你要寻找第一个 >=5 的数,你会发现,整个过程都在执行L=mid,最后得到的结果中,R是等于下标6的,他明显这个时候是越界的,说明我们找不到要寻找的数字,而如果我们一开始将R赋值为n-1,也就是赋值为下标5的时候,他返回的R是5,是没有越界的,被我们当成了答案,但其实这时候我们的二分是没有答案的,就发生了错误
   其次,L最小值为-1,R最小值只能取到1,因为L+1!=R为循环结束条件,R最大值为N,同理则L的最大值为N-2,则(L+R)/2的取值范围是 [0,N)
   mid的值始终位于0到N的左闭右开区间里面,不会发生越界的错误;

为什么循环结束的条件是while(L+1!=R)?

   之前学过二分的小伙伴可能会发现,之前学的二分,他循环结束的条件是while(L<R)
   而这边给出的循环条件是while(L+1!=R) 其实,就是当L和R相邻的时候,循环就结束,而原本的while(L<R)
是当两区间重合以后,循环才结束,所以之前我们需要判断对mid进行加一或者减一的操作,而且因为区间重合的问题,最后返回的L、R还要再进行判断,而这边的这个二分,因为区间反回的是不重合的两区间,只有L=mid和R=mid这两种情况,最后根据需要返回L或者R;

不会陷入死循环

   对于比较奇葩的情况,比如数组大小为1或者2
   比如int a[1],b[2];
   由于我们是while(L+1!=R)结束循环,也就是当L和R相邻的时候结束条件
   对于a[1],他的下标为0 此时L=-1,R=n也就是1
   对于b[2],他的下标为0,1 此时L=-1,R=n也就是2
   所以无论何种情况,初始的L+1始终小于R,历经循环后最终L和R相邻,不会出现一开始L就和R重合等情况导致出现while(L+1!=R)循环不能结束的情况

最后

   我们就能够通过二分得到不重合的两区间,而且只需要L=mid和R=mid,不需要考虑L=mid+1,R=mid-1的情况
   且记得一开始对于一个下标为0,1,2…n-1的数组,指针L要赋值为-1,指针R要赋值为n,那么你就学会了
   最后我给出y总基础算法中的二分例题
数的范围的这题的关于这个二分方法的代码实现

数的范围
#include<iostream>
using namespace std;
const int N=1e5+5;
int n,m,q[N];
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);
    while(m--)
    {
        int k;scanf("%d",&k);
        //寻找第一个等于K的坐标 我这边让二分的边界定为 左边为<5 右边>=5 则所求为r
        int l=-1,r=n;
        while(l+1!=r)//当l与r没有相接的时候,求边界
        {
            int mid=l+r>>1;
            //下面找第一个>=5的坐标
            if(q[mid]>=k) r=mid;
            else l=mid;
        }
        //此时得到的r是第一个>=5的坐标
        if(q[r]!=k) printf("-1 -1\n");
        else{
            printf("%d ",r);
                //现在找最后一个<=5的数字 我这边让二分的左边为<=5 右边为>5 则所求为ll
                int ll=-1,rr=n;
                while(ll+1!=rr)
                {
                    
                    int mid=ll+rr>>1;
                    if(q[mid]<=k) ll=mid;
                    else rr=mid;
                }
                if(q[ll]!=k) printf("%d\n",r);
                else printf("%d\n",ll);
            }
        
    }
    
}

四、

    例题one数的范围

    例题two数的三次方根

五、相关学习的视频链接-为啥二分查找容易出错

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

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

相关文章

骨传导耳机真不伤耳吗?骨传导耳机有什么好处?

骨传导耳机真不伤耳吗&#xff1f;骨传导耳机有什么好处&#xff1f; 我先来说说骨传导耳机的工作原理吧&#xff0c;骨传导是一种传声方式&#xff0c;声波通过颅骨、颌骨等头部骨头的振动&#xff0c;将声音传到内耳。其实骨传导的现象我们很常见&#xff0c;就像我们平时嗑瓜…

【总结】p49常见问题和快捷键汇总

p49常见问题和快捷键汇总 基础概念常用快捷键汇总编辑器快捷键&#xff08;不包括视口操作&#xff09;蓝图快捷键 中英文命名注意事项帧和秒的概念带星号的文件的意思编译的作用实例和原素材情景关联返回的快捷键 虚幻引擎闪退问题 基础概念 常用快捷键汇总 编辑器快捷键&am…

【图像去噪】基于原始对偶算法优化的TV-L1模型进行图像去噪研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

ruoyi-cloud-notes02

1、Validated RequestBody 配合使用 Validated 和 RequestBody 都是 Spring Boot 中用于在请求中验证数据的注解。但是&#xff0c;它们的作用和使用方式略有不同。 Validated 用于在方法参数、URL、请求体、Map中的数据上进行验证&#xff0c;确保数据的有效性。它会在验证失…

SpringBoot核心内容梳理

1.SpringBoot是什么? Spring Boot是一个基于Spring框架的快速开发应用程序的工具。它简化了Spring应用程序的创建和开发过程&#xff0c;使开发人员能够更快速地创建独立的、生产就绪的Spring应用程序。它采用了“约定优于配置”的原则&#xff0c;尽可能地减少开发人员需要进…

创建vue-cli(脚手架搭建)

目录 功能 需要的环境 使用HbuilderX快速搭建一个vue-cli项目 组件路由 element-ui vue-cli 官方提供的一个脚手架&#xff0c;用于快速生成一个 vue 的项目模板&#xff1b;预先定义 好的目录结构及基础代码&#xff0c;就好比咱们在创建 Maven 项目时可以选择创建一个 骨…

2019年09月《全国青少年软件编程等级考试》Python一级真题解析

一、单选题 第1题 关于Python的编程环境,下列的哪个表述是正确的? A:Python的编程环境是图形化的; B:Python只有一种编程环境ipython; C:Python自带的编程环境是IDLE; D:用windows自带的文本编辑器也可以给Python编程?,并且也可以在该编辑器下运行; 正确答案…

数据集相关网站(Open datasets and sources)

数据集相关网站(Open datasets and sources&#xff09; 数据集网站 Open datasets and sources政府数据网站 Government Data:金融数据网站 Financial Data Sources:犯罪数据网站 Crime Data:健康数据网站 Health Data:学术和商业数据网站 Academic and Business Data:其他数据…

Linux下进程的特点与环境变量

目录 进程的特点 进程特点的介绍 进程时如何实现并发性的 进程间如何切换 概念铺设 PC指针 上下文 环境变量 PATH 修改PATH HOME SHELL env 命令行参数 什么是命令行参数&#xff1f; 打印命令行参数 通过函数获得环境变量 getenv 命令行参数 env 修改环境变…

Compose:从重组谈谈页面性能优化思路,狠狠优化一笔

作者&#xff1a;晴天小庭 前言&#xff1a; 随着越来越多的人使用Compose开发项目的组件或者页面&#xff0c;关于使用Compose构建的组件卡顿的反馈也愈发增多&#xff0c;特别是LazyColumn这些重组频率较高的组件&#xff0c;因此很多人质疑Compose的性能过差&#xff0c;这…

flask服务生成证书文件,采用https访问,开启用户密码验证

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 3072开启用户密码验证 auth.verify_password def verify_password(username, password):if username abcdefg and password 1234546:return usernameapp.route(/post_request, methods[POST…

HDFS中的Federation联邦机制

HDFS中的Federation联邦机制 当前HDFS体系架构--简介局限性 联邦Federation架构简介好处配置示例 当前HDFS体系架构–简介 当前的HDFS结构有两个主要的层&#xff1a; 命名空间&#xff08;namespace&#xff09; 由文件&#xff0c;块和目录组成的统一抽象的目录树结构。由n…

JavaScript |(五)DOM简介 | 尚硅谷JavaScript基础实战

学习来源&#xff1a;尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版 文章目录 &#x1f4da;DOM简介&#x1f4da;DOM查询&#x1f407;文档的加载&#x1f407;节点&#x1f407;节点的属性&#x1f407;元素节点的子节点&#x1f407;获取父节点和兄弟节点&#x1…

4,链表【p5】

链表 4.1哈希表简介4.2有序表简介4.3链表4.3.1例1-反转单向和双向链表4.3.2例2-打印两个有序链表的公共部分4.3.3面试时链表解题的方法论4.3.4例3-判断一个链表是否为回文结构4.3.4.1快慢指针 4.3.5例4-将单向链表按某值划分成左边小、中间相等、右边大的形式4.3.6例5-复制好友…

redis 原理 7:开源节流 —— 小对象压缩

Redis 是一个非常耗费内存的数据库&#xff0c;它所有的数据都放在内存里。如果我们不注意节约使用内存&#xff0c;Redis 就会因为我们的无节制使用出现内存不足而崩溃。Redis 作者为了优化数据结构的内存占用&#xff0c;也苦心孤诣增加了非常多的优化点&#xff0c;这些优化…

【JavaEE初阶】了解JVM

文章目录 一. JVM内存区域划分二. JVM类加载机制2.1 类加载整体流程2.2 类加载的时机2.3 双亲委派模型(经典) 三. JVM垃圾回收机制(GC)3.1 GC实际工作过程3.1.1 找到垃圾/判定垃圾1. 引用计数(不是java的做法,Python/PHP)2. 可达性分析(Java的做法) 3.1.2 清理垃圾1. 标记清除2…

CMake:检测python解释器和python库

CMake:检测python解释器和python库 导言检测python解释器CMakeLists.txt输出附录 检测python库项目结构CMakeLists.txt相关源码附录 导言 python是一种非常流行的语言。许多项目用python编写的工具&#xff0c;从而将主程序和库打包在一起&#xff0c;或者在配置或构建过程中使…

企业集团员工内部食堂餐厅食材预定订餐统计系统开发

内部食堂是针对员工食堂设计的预定系统 可以提前进行点餐,统计餐食人数 定量制作,避免浪费食材。 首页预定菜单提前显示一周菜单 用户可以提前预定想要购买的餐品 在用餐时取餐核销 食堂平台方用餐时对用户的菜品进行核销 通过后台预订信息 根据报餐统计做出对应数量…

Example: Beam Allocation in Multiuser Massive MIMO阅读笔记一

文章目录 A Machine Learning FrameworkApplication of Supervised Learning to Resource AllocationResearch Challenges and Open IssuesLow-Complexity ClassifierMulti-BS CooperationFast Evolution of Scenarios Conclusion A Machine Learning Framework 对于现有的云计…

python在函数中更改外部变量值

目录 前言 列表、字典&#xff08;可变对象&#xff09; 元组&#xff08;不可变对象&#xff09; 全局变量 前言 今天在写LeetCode题时&#xff0c;发现一个问题我并没有掌握&#xff0c;那就是如何在Python的函数中更改变量值&#xff08;包括列表&#xff0c;字典&…