算法:二分查找算法/朴素二分/查找区间左右端点二分

news2024/12/23 5:44:53

文章目录

  • 实现原理
    • 查找区间左右端点
      • 查找左端点
      • 查找右端点
  • 实现思路
    • 朴素二分查找模板
    • 查找区间左右端点模板
  • 典型例题
    • 二分查找
    • 查找元素第一个和最后一个位置
    • x的平方根
    • 山脉数组峰顶索引
  • 总结

实现原理

通常来说,二分查找的使用范围是当数组有序的时候可以使用,可以进行对有序数列的搜索,但其实这样的说法不完全正确

严格来说,二分查找可以适用于有二段性的数组序列中,二段性就是可以把一个数组的区间划分为两个部分,然后通过一定的判断舍弃掉其中一部分,在另外一个区间内继续寻找,这样的数组序列就是有二段性的序列,因此,数组有序是具有二段性的一种情况,但是二段性并非要求一定是要有序的

查找区间左右端点

查找左端点

这个算法原理是朴素二分的一个延伸,它的使用范围通常作用于例如要寻找一段符合二段性序列的子区间的情况,例如现在有序列1,2,3,3,3,3,4,我们要寻找的是包含3的这段区间的下标情况,因此这里就需要进行这段区间左右端点的寻找

首先是进行左端点的寻找:

核心思维不变,依旧是找中间然后进行左右区间的简化,但是和朴素二分查找比起来却也有很多需要进行注意的地方

算法思路:

算法思路和前面相比有一些不同,以上面的例子为例,假设我们要寻找的是3,那么就将这个区间划分为两个部分,小于3的部分和大于等于3的部分

那么我们定义了leftright指针,当两个指针求出mid指针后,就可以进行分类讨论了:

  1. mid对应的下标小于3:此时意味着mid对应的值一定不是我们需要的值,因此这里就可以放心的让left=mid+1
  2. mid对应的下标大于等于3:此时意味着mid已经落到了我们要关注的区间内,那么此时right就不能再和朴素二分查找一样选择right=mid-1了,应该把他改为right=mid,才能符合要求,否则可能会遗漏掉右边区间的数据

细节处理:

  1. 循环条件的判断要采用left<right
  2. left == right的情况下,就是最终结果,不需要进行判断了
  3. 如果进行判断,就会死循环
  4. 求中点的操作:
  • mid=left+(right-left)/2
  • mid=left+(right-left+1)/2

对于朴素二分来说,这两种都是可以的,究其本质这两个的区别是,当序列的数量是偶数的时候,查找到的中间元素其实是两个数,上面的式子对应的是这两个数中的左数,下面的式子对应的是这两个数中的右数

而在这里端点寻找的算法中,只能采用上面的式子,原因其实和算法原理中对右区间的处理有分不开的联系,如果这里采用的是下面的式子,那么mid的值更新和right的值更新是相同的,就会陷入死循环,程序跑不下去

查找右端点

和查找左端点的算法相同,查找右端点也是基于二段性,分为小于等于的区间和大于的区间,不同的点在于leftright的处理方式和选中点的形式和前面相反

  • left=mid

  • right=mid-1

  • mid=left+(right-left+1)/2


实现思路

和前面的算法不同,二分查找拥有一定的模板性,但模板并非硬套,需要在实际理解二分算法的本质的前提下,进而利用模板类的语句更方便的解决二分查找的问题

朴素二分查找模板

while (left <= right)
{
    int mid = left + (right - left) / 2;
    if (nums[mid] == target)
    {
        return mid;
    }
    else if (nums[mid] < target)
    {
        left = mid + 1;
    }
    else
    {
        right = mid - 1;
    }
}

查找区间左右端点模板

这个模板也是基于题目总结出的

while (left < right)
{
    int mid = left + (right - left) / 2;
    if (nums[mid] < target)
    {
        left = mid + 1;
    }
    else
    {
        right = mid;
    }
}
while (left < right)
{
    int mid = left + (right - left + 1) / 2;
    if (nums[mid] > target)
    {
        right = mid - 1;
    }
    else
    {
        left = mid;
    }
}

下面出现-1的时候上面就+1


典型例题

二分查找

在这里插入图片描述

最入门的一道题,从中可以抽离出朴素二分查找模板

class Solution 
{
public:
    int search(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size()-1;
        while(left<=right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]==target)
            {
                return mid;
            }
            else if(nums[mid]<target)
            {
                left=mid+1;
            }
            else
            {
                right=mid-1;
            }
        }
        return -1;
    }
};

查找元素第一个和最后一个位置

在这里插入图片描述

class Solution 
{
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        vector<int> v;
        if(nums.size()==0)
        {
            return {-1,-1};
        }
        int left=0,right=nums.size()-1;
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(nums[mid]<target)
            {
                left=mid+1;
            }
            else
            {
                right=mid;
            }
        }
        nums[left]==target? v.push_back(left) : v.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;
            }
        }
        nums[right]==target? v.push_back(right) : v.push_back(-1);
        return v;
    }
};

x的平方根

在这里插入图片描述

class Solution 
{
public:
    int mySqrt(int x) 
    {
        if(x==0 || x==1)
        {
            return x;
        }
        int left=1,right=x/2;
        while(left<right)
        {
            long long mid=left+(right-left+1)/2;
            if(mid*mid<=x)
            {
                left=mid;
            }
            else
            {
                right=mid-1;
            }
        }
        return left;
    }
};

对上面查找左右端点二分的另外一个应用,是上面的简化版,只需要查找一半,这里需要注意的是,在使用模板前要想清楚是如何进行分类讨论的,我们这里采用的分类讨论的思想是,如果平方的和小于等于x就保留,如果大于x就直接舍弃,这就是对这段区间的二段性进行的讨论,因此如果mid落入了大于x的区间内就直接被舍弃,right=mid-1,下面出现减号上面就加号,本质上是因为要考虑到中间两个数答案恰好落在左边的情况

山脉数组峰顶索引

在这里插入图片描述

class Solution 
{
public:
    int peakIndexInMountainArray(vector<int>& arr) 
    {
        int left=0,right=arr.size()-1;
        while(left<right)
        {
            int mid=left+(right-left+1)/2;
            if(arr[mid]>arr[mid-1])
            {
                left=mid;
            }
            else
            {
                right=mid-1;
            }
        }
        return left;
    }
};

本题就体现出,二分查找未必一定要求是有序,其实只要包含二段性就可以使用二分查找,在这个题的原理中,这个序列有天然的二段性,即左边满足严格大于,右边满足严格小于,由于题目保证长度大于等于3,因此这里采用的是让midmid-1对应的数据进行比较,因此我们就把二段性划分成两部分:左边严格递增一段,右边严格递减一段,如果mid落在了严格递减的这段区间内,表示mid一定不会是这段区间,因此就选择right=mid-1,而如果落在左边的区间内,就代表着mid不确认是不是最高的点,因此就选择让mid=left


总结

二分查找是多种算法中少数的,可以把时间复杂度控制在logN的算法,是一种效率很高的算法,在实际的算法题目中只要出现了二段性相关的题目,就可以使用二分查找进行寻找,具体的模板实现是很简单的,但重点是要懂得模板背后的原理,才能正确使用模板进行使用

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

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

相关文章

2023年夏季《移动软件开发》实验报告2

2023年夏季《移动软件开发》实验报告 姓名和学号&#xff1f;本实验属于哪门课程&#xff1f;中国海洋大学23夏《移动软件开发》实验名称&#xff1f;实验2&#xff1a;天气查询小程序博客地址&#xff1f;XXXXXXXGithub仓库地址&#xff1f;XXXXXXX &#xff08;备注&#x…

MyBaits注解开发

1、注解开发介绍 在过去使用框架开发项目&#xff0c;基本都采用xml作为框架的核心配置文件存在&#xff0c;但是这种方式开发效率还是比较地下、不灵活。 现在企业开发为了能够更快的提高开发效率&#xff0c;必然会使用企业级框架进行项目开发&#xff0c;而现在主流的框架…

华人画家戴渭作品 3000 万拍出,牛津艺术学院发出任教邀请

爱丁堡,2023年7月 - 画家戴渭以他独特的画风、深邃的意境和慈悲智慧的属性,将艺术与宗教融合于作品之中。初看他的作品,可能会被其高超的艺术水准所震撼,然而仔细品味,方能领略到他深邃的艺术造诣与宗教智慧的深度融合。 作为国内最年轻的华人80后画家之一,戴渭近期被英国牛津…

若依cloud -【 22 ~ 25 】

22 认证中心介绍 1 概述 用户身份认证的过程ruoyi-cloud认证中心的实现没有依赖任何插件&#xff0c;相对简单&#xff0c;一看就懂从架构图的角度看认证中心&#xff1a; 登录请求&#xff0c;进到网关网关直接调用认证中心。查看ruoyi-gateway-dev.yml&#xff1a; # 结论…

【历史上的今天】8 月 22 日:改变世界的程序员们;网络直播的鼻祖;何小鹏离开阿里巴巴

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天 2023 年 8 月 22 日。历史上的今天&#xff0c;Masatoshi Shima 出生&#xff0c;他和 英特尔&#xff08;Intel&#xff09; 合作设计的芯片让第一个微处理器 Intel 400…

【SpringSecurity】二、密码处理与获取当前登录用户

文章目录 一、密码处理1、加密方案2、BCryptPasswordEncoder类初体验3、使用加密码加密 二、获取当前登录用户1、方式一&#xff1a;通过安全上下文的静态调用2、方式二&#xff1a;做为Controller中方法的参数3、方式三&#xff1a;从HTTPServletRequest中获取4、方式四&#…

无涯教程-PHP Installation on Windows NT/2000/XP with IIS函数

在Windows Server上运行IIS的PHP的安装比在Unix上简单得多,因为它涉及的是预编译的二进制文件而不是源代码。 如果您打算在Windows上安装PHP,那么这是先决条件列表- 运行中的PHP支持的Web服务器。一个正确安装的PHP支持的数据库,如MySQL或Oracle等。(如果您打算使用的话) PHP…

smiley-http-proxy-servlet 实现springboot 接口反向代理,站点代理,项目鉴权,安全的引入第三方项目服务

背景&#xff1a; 项目初期 和硬件集成&#xff0c;实现了些功能服务&#xff0c;由于是局域网环境&#xff0c;安全问题当时都可以最小化无视。随着对接的服务越来越多&#xff0c;部分功能上云&#xff0c;此时就需要有一种手段可以控制到其他项目/接口的访问权限。 无疑 反向…

硬件解码example

使用方法&#xff1a; ./hw_decode vaapi juren-30s.mp4 juren-30s.mp4 验证播放&#xff1a; ffplay -video_size 1920x1080 -pixel_format yuv420p juren-30s.yuv av_hwdevice_iterate_types(type)如果你填入的参数不对&#xff0c;那么这函数这个函数的作用相当于以下命令&…

飞天使-k8s基础组件分析-pod

文章目录 pod介绍pod 生命周期init 容器容器handlerpod中容器共享进程空间sidecar 容器共享 参考链接 pod介绍 最小的容器单元 为啥需要pod? 答: 多个进程丢一个容器里&#xff0c;会因为容器里个别进程出问题而出现蝴蝶效应&#xff0c;pod 是更高级的处理方式pod 如何共享相…

简述docker映射(Mapping)和挂载(Mounting)

映射的概念&#xff1a; 将容器内的端口映射到主机的端口上&#xff0c;这样就可以通过主机的网络接口与容器内部进行通信。主机上对应端口的请求会被转发到容器内部&#xff0c;从而实现对容器内部程序的通信访问&#xff08;注意&#xff01;这里提到的容器内部的端口并不一定…

网络安全(黑客)了解学习路线

谈起黑客&#xff0c;可能各位都会想到&#xff1a;盗号&#xff0c;其实不尽然&#xff1b;黑客是一群喜爱研究技术的群体&#xff0c;在黑客圈中&#xff0c;一般分为三大圈&#xff1a;娱乐圈 技术圈 职业圈。 娱乐圈&#xff1a;主要是初中生和高中生较多&#xff0c;玩网恋…

EasyImage简单图床 - 快速搭建私人图床云盘同时远程访问【无公网IP内网穿透】

憧憬blog主页 在强者的眼中&#xff0c;没有最好&#xff0c;只有更好。我们是移动开发领域的优质创作者&#xff0c;同时也是阿里云专家博主。 ✨ 关注我们的主页&#xff0c;探索iOS开发的无限可能&#xff01; &#x1f525;我们与您分享最新的技术洞察和实战经验&#xff0…

阿里云CDN加速器基本概念与购买开通

文章目录 1.CDN加速器的基本概念1.1.CDN加速器基本介绍1.2.网站引入CDN加速器的架构图1.3.CDN加速器的工作原理1.4.引入CDN后域名解析变成了CNAME&#xff1f; 2.开通阿里云CDN加速服务 1.CDN加速器的基本概念 CDN加速器官方文档&#xff1a;https://help.aliyun.com/product/…

USB音频芯片SSS1700 鑫创优势替代CM6533参考设计|SSS1700规格24bit 96KHZ |替换CM6533方案

Cmedia CM6533是一款US B音频编解码器&#xff0c;内部嵌入8051内核&#xff0c;适用于耳麦&#xff0c;移动娱乐设备直插移动音箱&#xff08;docking&#xff09;&#xff0c;US B音箱&#xff0c;US B麦克风等应用。通过内部8051可以研发出各种应用&#xff0c;例如微软语音…

vue3 pdf、word等文件下载

效果&#xff1a; <div class"byLawBox"><div class"titleBox">规章制度公示</div><div class"contentBox"><TableList:loading"byLawloading"ref"byLawtablistRef":hasImport"false"…

Unity - 特殊文件夹

地址记录&#xff1a;https://www.cnblogs.com/zouqiang/p/6841399.html Assets Assets文件夹是unity项目中放置游戏资源的主文件夹。 该文件夹中的内容将直接反应在编辑器的Project视口中。许多系统API基于该文件夹路径。 Resources Unity允许你按需动态加载游戏资源到场景中…

ubuntu 对多CPU统一设置高性能模式

一、问题描述 之前在网上找到的CPU设置高性能模式&#xff0c;只能设置CPU0单个CPU&#xff0c;下述是对多核CPU统一设置工作模式。 二、软件安装与设置 执行下述命令sudo apt-get install indicator-cpufreq,然后重启电脑。此时&#xff0c;界面右上角会出现如下图标&#xf…

爬虫异常捕获与处理方法详解

Hey&#xff01;作为一名专业的爬虫代理供应商&#xff0c;我今天要和大家分享一些关于爬虫异常捕获与处理的方法。在进行爬虫操作时&#xff0c;我们经常会遇到各种异常情况&#xff0c;例如网络连接错误、请求超时、数据解析错误等等。这些异常情况可能会导致程序崩溃或数据丢…

威班8.19PMP考试爱心送考再出发,能量补给站为学员提供考试保障

8月19日&#xff0c;2023年的第三场PMP考试准时开考。 对于准备了个把月的学员们来说&#xff0c;这一时刻无比重要&#xff0c;为了给威班的PMP学员们考试加油打气&#xff0c;威班特地组织了送考活动&#xff0c;在考场外提前布置应援点&#xff0c;给前去参加考试的学员们带…