【算法】二分查找——在排序数组中查找元素的第一个和最后一个位置

news2025/1/20 5:09:17

本节博客主要是通过“在排序数组中查找元素的第一个和最后一个位置”总结关于二分算法的左右界代码模板,有需要借鉴即可。

目录

  • 1.题目
  • 2.二分边界算法
    • 2.1查找区间左端点
      • 2.1.1循环条件
      • 2.1.2求中点的操作
      • 2.1.3总结
    • 2.2查找区间右端点
      • 2.1.1循环条件
      • 2.1.2求中点的操作
      • 2.1.3总结
    • 2.3总结
  • 3.参考解题代码
  • 4.模板总结
  • 5.总结

1.题目

题目链接:LINK
在这里插入图片描述

这个题要求我们求这个排序数组的一个元素的开始位置与结束位置。

可以用暴力求解的方法,把第一次出现的数字下标记录一下,最后一次记录一下,返回结果,除了复杂度差之外没什么不好的。

当然我们这里说一下二分算法的思想。之所以可以使用二分算法,这是因为该数组是有序的,可以利用二分算法的“二段性”将其分割。


用两次二分算法:

  • 一方面,我们可以将整个数组分为大于等于t和小于t来找left点

  • 另一方面,我们可以将整个数组分为大于t和小于等于t来找right点

但是这里有一些代码细节值得注意!!!

2.二分边界算法

2.1查找区间左端点

在这里插入图片描述

思考:我们在寻找左端点时候为什么要对数组按照小于t和大于等于t进行划分?
答:关键是因为我们要找左端点,左端点一定不可能在小于t的区间里。
在这里插入图片描述

通过上面的图片可知,我们要想找到一个数的左端点,那么这个左端点(我们要寻找的点)一定不再大于t这个区域,所以我们可知

  • mid < ret时,left = mid + 1
  • mid >= ret时,right = mid

2.1.1循环条件

while(left < right)//... √
while(left <= right)//... ×

循环条件选:left < right

这里为什么不是left <= right 呢?

  • left==right的情况下,即是最后结果,无需进行重复判断。
  • 可能有些情况下会出现死循环问题
    下面是对上面两个理由进行论证:
    在所有可能情况中,无非存在三种情况,
  • ①left与right中间存在要找的ret点
    在这里插入图片描述
    此时,mid = ret,mid == right,那么left = mid,会不断进入循环,陷入死循环
  • ②left与right中间所有点全部大于我们要找的右端点
    在这里插入图片描述
    到了最后,mid > ret, mid = right,right = mid,会存在死循环问题
  • ③left与right中间所有点全部小于我们要找的右端点
    在这里插入图片描述
    mid < ret,left = mid + 1,不会出现死循环问题。

2.1.2求中点的操作

我们求中点无非两种求法

①mid = left + (right - left) / 2; √
②mid = left + (right - left + 1) / 2; ×

这俩主要区别就是在数字个数是偶数情况下,①式取靠左的中点;②式取靠右的中点。

然后对于查找区间右端点而言,必须选用①式。
为什么,下面来进行解释?
如果选用②式,会存在下面情况:比如,mid指向right,然后mid所在的值>=ret值,就会不断死循环
注:if mid >= ret,right = mid;

在这里插入图片描述

2.1.3总结

在求目标值左端点时候,第一循环条件不能有等于,第二是求中点要用靠右中点。

2.2查找区间右端点

在这里插入图片描述

通过上面的图片可知,我们要想找到一个数的左端点,那么这个右端点(我们要寻找的点)一定不再大于t这个区域,所以我们可知

  • mid <= ret时,left = mid
  • mid > ret时,right = mid - 1

2.1.1循环条件

while(left < right)//... ×
while(left <= right)//... √

循环条件选:left < right

这里为什么不是left <= right 呢?

  • left==right的情况下,即是最后结果,无需进行重复判断。
  • 可能有些情况下会出现死循环问题

下面是对上面两个理由进行论证:
在所有可能情况中,无非存在三种情况,

  • ①left与right中间存在要找的ret点
    在这里插入图片描述
    此时,mid = ret,mid == right,那么right = mid,会不断进入循环,陷入死循环。
  • ②left与right中间所有点全部大于我们要找的右端点
    在这里插入图片描述
    到了最后,mid > ret,mid == right,right = mid - 1,不会出现死循环问题
  • ③left与right中间所有点全部小于我们要找的右端点
    在这里插入图片描述
    mid < ret,left = mid,此时会出现死循环问题

2.1.2求中点的操作

我们求中点无非两种求法

①mid = left + (right - left) / 2; ×
②mid = left + (right - left + 1) / 2;

这俩主要区别就是在数字个数是偶数情况下,①式取靠左的中点;②式取靠右的中点。

然后对于查找区间右端点而言,必须选用②式。
为什么,下面来进行解释?
如果选用①式,会存在下面情况:比如,mid指向left,然后mid所在的值<=ret值,left = mid,如此就会不断死循环
注:if mid <= ret,left = mid;
在这里插入图片描述

2.1.3总结

在求目标值右端点时候,第一循环条件不能有等于,第二是求中点要用靠右中点。

2.3总结

找左端点:
在这里插入图片描述

  • mid < ret时,left = mid + 1
  • mid >= ret时,right = mid
while(left < right)//...
mid = left + (right - left) / 2;

找右端点:
在这里插入图片描述

  • mid <= ret时,left = mid
  • mid > ret时,right = mid - 1
while(left < right)//...
mid = left + (right - left + 1) / 2;

根据上面的算法总结我们可以解决上面题目

3.参考解题代码

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        vector<int> ret;
        //处理特殊情况
        if(nums.size() == 0)
        {
            ret.push_back(-1);
            ret.push_back(-1);

            return ret;
        }

        int left = 0, right = nums.size() - 1;
        //处理左端点
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] >= target)
            {
                right = mid;
            }
            else
            {
                left = mid + 1;
            }
        }
        if(nums[left] == nums[right] && nums[left] == target)
        {
            ret.push_back(left);
        }
        else
        {
            ret.push_back(-1);
        }

        //处理右端点
        left = 0, right = nums.size() - 1;
        while(left < right)
        {
            int mid = left + (right - left + 1) / 2;
            if(nums[mid] > target)
            {
                right = mid - 1;
            }
            else
            {
                left = mid;
            }
        }
        if(nums[left] == nums[right] && nums[right] == target)
        {
            ret.push_back(right);
        }
        else
        {
            ret.push_back(-1);
        }


        return ret;
    }
};

4.模板总结

在这里插入图片描述

5.总结

这个题目我感觉掌握了二分边界代码原理其实不难,重点肯定是那个二分边界算法原理,需要自己多理解一下。


EOF

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

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

相关文章

FebHost:为什么企业需要注册保加利亚.BG域名?

在当今全球化的商业环境中&#xff0c;对于与保加利亚市场息息相关的企业而言&#xff0c;选择合适的域名至关重要。.BG域名作为企业在线身份的重要组成部分&#xff0c;提供了多重利好&#xff0c;成为业内不容忽视的战略资源。 首先&#xff0c;地域标识性强是.BG域名的一大…

ArrayList和LinkedList的使用

ArrayList List<> list new ArrayList<>(); LinkedList

深入理解 House of Cat

Index 序言利用 FSOP 调用 House of Cat利用条件伪造IO流条件完整调用链分析 模板System (one_gadget) 模板ORW模板 Demo & Exp利用 __malloc_assert 调用 House of Cat例题&#xff1a;题目思路Exp 序言 原文章&#xff1a;深入理解 House of Cat 随着 GNU 持续不断的更…

【Linux-IMX6ULL-DDR3简介测试-RGBLCD控制原理】

目录 1. DDR3 简介1.1 前要基本概念RAM & ROM 2. DDR3测试及初始化3. RGBLCD简介及控制原理3.1 RGBLCD简介3.2 RGBLCD-时序-像素时钟-显存3.2.1 RGB LCD时序3.2.2 像素时钟&#xff08;800*400分辨率&#xff09;3.2.2 显存&#xff08;800*400分辨率&#xff09; 3.3 RGBL…

Spring注解解析:条件注解@Condition注解和@ConditonOnXXX注解

文章目录 一、条件注解二、Conditional1、使用方法2、示例 一、条件注解 条件注解的作用是给需要装载的Bean增加一个条件判断。只有满足条件才会装在到IoC容器中。而这个条件可以由自己去完成的&#xff0c;可以通过重写Condition接口重写matches()方法去实现自定义的逻辑。所…

.NET 分享一款Web打包和解压缩工具

01本文概要 在.NET部署环境中&#xff0c;利用IIS中间件开启对ASP的支持&#xff0c;可以实现许多强大的文件操作功能。特别是在一些需要进行预编译的情况下&#xff0c;通过上传ASP脚本&#xff0c;可以获得WebShell&#xff0c;从而方便地进行各种操作。本文将介绍一个名为S…

运动耳机怎么选?五款新手必买的运动耳机盘点

运动耳机是专为运动爱好者设计的耳机&#xff0c;轻巧便携&#xff0c;佩戴稳固。无论你在跑步、健身还是骑行&#xff0c;它都能为你带来优质的音乐体验。那如何选择一款合适的运动耳机呢&#xff1f;这里&#xff0c;我结合自己和身边朋友平时选购经验&#xff0c;整理了一些…

sklearn机器学习编程练习大全(二)

sklearn机器学习编程练习大全&#xff08;二&#xff09; 第11题 从字符串提取标签第12题 IRIS数据集探索第13题 构建模型&#xff0c;计算准确率第14题 预估目标列编码第15题 one-hot编码 第11题 从字符串提取标签 DataFrame如下&#xff1a; 如何将以上的DataFrame变成如下的…

python批量生成25位数字字母混合序列号(SN码)

欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一.前言 二.代码 三.使用 四.分析 一.前言 SN码,即Serial Number的缩写,有时也被称为Serial No,是产品序列号的意思。它是一个独特的标识符,用于区分同一种类

第二证券资讯|昨夜,黄金大涨、美股创新高!人民币狂拉

受降息预期影响&#xff0c;美股三大指数团体创新高&#xff0c;黄金期现价格亦大幅走高。 当地时间5月15日星期三&#xff0c;美股三大股指全线收涨。道指涨0.88%&#xff0c;纳指涨1.40%&#xff0c;标普500指数涨1.17%。 经济数据方面。美国4月CPI同比上涨3.4%&#xff0c…

每日一练 2025.5.16

题目&#xff1b; 给定一个非负整数&#xff0c;你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释: 交换数字2和数字7。示例 2 : 输入: 9973 输出: 9973 解释: 不需要交换。注意: 给定数字的范围是 [0, 108] 解题&#…

首战告捷!KCM Trade漂移队出征2024日本漂移锦标赛(FDJ2)

卓越之姿&#xff0c;非凡之势&#xff01;KCM Trade漂移队以实力点燃激情 当激情与速度交织&#xff0c;当硝烟四起的战场转移到赛车领域&#xff0c;我们见证了一场精彩绝伦、实力与策略并存的较量——KCM Trade漂移队在2024日本漂移锦标赛&#xff08;FDJ2&#xff09;上展现…

AIGC文生视频:Sora模型报告总结

作为世界模拟器的视频生成模型 我们探索视频数据生成模型的大规模训练。具体来说&#xff0c;我们在可变持续时间、分辨率和宽高比的视频和图像上联合训练文本条件扩散模型。我们利用对视频和图像潜在代码的时空补丁进行操作的变压器架构。我们最大的模型 Sora 能够生成一分钟…

惠海 H4112 同步整流30V降压芯片IC 24V转12V5V3.3V3.5A方案EN使能控制

惠海H4112同步整流30V降压芯片IC是一款DCDC电源管理芯片&#xff0c;它具备精确恒压和恒流的同步降压能力&#xff0c;适用于多种应用场景&#xff0c;如汽车充电器、照明灯、便携式设备供电电源和电池充电器等。 输出电压与电流调整&#xff1a; H4112支持输出电压在2.5V到2…

大模型时代,交换机技术演变、性能分析、衡量指标

OSI协议及在高性能计算中向RDMA的过渡 协议是为计算机网络内的数据交换而建立的一组规则、标准或协议。在法律层面&#xff0c;OSI七层协议被视为国际标准。该协议于20世纪80年代引入&#xff0c;旨在通过其七层网络模型标准化计算机间通信&#xff0c;以满足开放网络的要求。…

wamp 安装 PHP8

最近的项目需求&#xff0c;需要将PHP 升级8使用&#xff0c;一直都是用wamp &#xff0c;所以需要在wamp集成PHP8 1、首先下载 php8 的包。地址&#xff1a; PHP: Downloadshttps://www.php.net/downloads.php 下载版本是目前最新的 PHP8.3.7&#xff0c;不要下载nts 版本&a…

【MySQL精通之路】MySQL8.0官方文档-数据字典

目录 16.1 数据字典架构 如何升级数据字典 使用MySQL的调试版本查看数据字典表 16.2 删除基于文件的元数据存储 .frm文件 .par文件 .TRN文件 .TRG文件 .isl文件 db.opt文件 ddl_log.log文件 16.3 字典数据的事务存储 16.4 字典对象缓存 表空间定义缓存分区&#…

HTML(3)——常用标签3

引用标签 1.<blockquote>和<q> 两者都是对文本的解释引用&#xff0c;<blockquote>是用较大的段落进行解释&#xff0c;<q>是对较小的段落进行解释。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UT…

人工智能(一)架构

一、引言 人工智能这个词不是很新鲜&#xff0c;早就有开始研究的&#xff0c;各种推荐系统、智能客服都是有一定的智能服务的&#xff0c;但是一直都没有体现出多高的智能性&#xff0c;很多时候更像是‘人工智障’。 但是自从chatGpt3被大范围的营销和使用之后&#xff0c;人…

提升工作效率,畅享Microsoft Office 2016 for Mac/win软件

Microsoft Office 2016 for Mac/win是一款功能强大的办公软件套件&#xff0c;为用户提供了一系列高效、易用的工具&#xff0c;帮助您在工作和学习中更加高效地处理各种任务。无论您是学生、职场人士还是企业管理者&#xff0c;这款软件都能满足您的各种需求。 首先&#xff…