【算法笔记】二分查找 红蓝染色法

news2024/9/23 16:49:34

目录

  • 二分查找 红蓝染色法(感谢灵神)
    • 闭区间[left, right]
    • 左闭右开区间[left, right)
    • 开区间(left, right)
    • 变式

二分查找 红蓝染色法(感谢灵神)

这里是灵神的教学视频:二分查找 红蓝染色法_哔哩哔哩_ bilibili

学了二分查找之后其实一直不是很理解,直到昨天看了灵神的讲解,有了全新的理解,有一种直冲天灵盖的感觉,写个笔记整理一下,感谢灵神

对于一个有序数组,我们如果想查找其中的某一个元素,我们可以通过从头遍历其中的所有元素,如果有匹配的元素,则返回元素的值,但是这种暴力解法不但没有利用有序数组这个特点,而且时间复杂度是O(n),不是很有效率。

这个时候我们可以采用二分查找的方式:每次排除一半的元素,这样我们每查找一个元素的时候,他的时间复杂度就是O(logn),要比暴力解法好很多。

二分查找中我们会涉及到一些变量,以及他们在每一轮循环中的变化情况:左右游标left、right,中间游标mid,以及我们要找的值target,其中左右游标用于在每次循环中缩小我们的查找区间确定区间外数值的大小,mid游标用于与target值进行比较,辅助左右游标的具体移动情况。

闭区间[left, right]

下面我们介绍在闭区间[left, right]内查找的情况:

  1. 我们将left游标初始化为数组的起始下标0right初始化为数组末尾的下标arr.length-1,mid指向左右游标的中间值left+(right - left)/2,这样我们每次就可以排除一半的数据,是最优解。

    left+(right - left)/2这里为什么这样写,是因为防止在Java中直接进行left+right导致整型数字太大导致越界的情况

  2. 我们将 < t a r g e t < target <target的元素标记为红色, ≥ t a r g e t \geq target target的元素标记为蓝色,但是我们要清楚,区间内的元素我们是不知道它们的颜色的,这点很重要!!假定我们现在要查找的数组为:[5,7,7,8,8,10],target值为8,游标的位置如下图:

    在这里插入图片描述

  3. 经过比较之后,我们发现mid指向的值为7,满足 < t a r g e t < target <target的条件,那么我们将left更新为mid+1,原有的元素变为如下的颜色:

    在这里插入图片描述

    这里为什么不更新为mid??

    这也是我一直不太清楚的一个点,现在我来试着说一下:因为我们选择的方式是在闭区间[left, right]内查找,所以我们要保证被比较过的元素在区间外面,没有比较过的元素在区间内部,而mid是我们比较的最后一个元素,那么我们只需要将游标更新为mid+1或者是mid-1就可以保证区间内的元素都是未经比较的,并且区间外的元素都是已经确定颜色的

  4. 继续进行比较,mid指向的值为8满足 ≥ t a r g e t \geq target target的条件,此时我们不确定的区间也就是[left, mid-1],所以我们更新右游标到mid-1的位置,保证区间外的元素都已经确定过:

    在这里插入图片描述

  5. 继续进行比较,mid指向8,满足 ≥ t a r g e t \geq target target条件,再次更新右游标到mid-1的位置:

    在这里插入图片描述

  6. 到这个时候我们发现:整个数组已经全部染色,也就意味着我们确定了所有元素和目标元素的大小关系,我们要清楚一个关键点:right+1指向的元素一定是蓝色( ≥ t a r g e t \geq target target),left-1指向的元素一定是红色( < t a r g e t <target <target,每次循环的过程中这个是不会变的,为了方便记忆灵神给这个关键点取名叫:循环不变量,我们清楚这一点之后,再去看那些循环条件或者是游标移动的位置,就很容易判断应该怎么写了。那么我们这里要找的元素8的位置也就找到了,直接返回下标right+1,或者是left就可以

我们看一下代码部分:

    public static int lower_bound(int[] nums, int target){
        int left = 0;
        int right = nums.length - 1;
        while (left <= right){ // 闭区间内查找,当left > right的时候区间为空 
            int mid = left + (right -left) / 2;
            if (nums[mid] < target){
                left = mid + 1; // [mid + 1, right]是不确定的
            } else {
                right = mid - 1; // [left, mid - 1]是不确定的
            }
        }
        return left; // left所指向的位置就是元素出现的初始位置
    }

左闭右开区间[left, right)

左闭右开区间和闭区间的情况相似,我们需要修改右游标的初始位置arr.length,因为右游标不再包括在区间内,也就是说再循环中[right, arr.length-1]的元素是确定好的;还需要修改的地方有右游标更新的位置,因为是开区间,所以直接移动到mid所在的位置就可以;最后是循环的终止条件,当left == right的时候区间为空,循环停止。下面是游标的初始位置:

在这里插入图片描述

那么我们开始循环:

  1. mid所指向的值为8,满足条件 ≥ t a r g e t \geq target target,我们将右游标移动至mid位置,并更新mid

    在这里插入图片描述

  2. mid所指向的值为7,满足条件 < t a r g e t < target <target,我们将左游标移动到mid+1的位置,并更新mid

    在这里插入图片描述

  3. mid所指向的值为7,满足条件 < t a r g e t < target <target,我们将左游标移动到mid+1的位置,并更新mid

    在这里插入图片描述

  4. 此时left == right,所有元素也都知道了大小,停止循环,并返回right。

代码部分

    public static int lower_bound(int[] nums, int target){
        int left = 0;
        int right = nums.length;
        while (left < right){ // 左闭右开区间内查找[left, right)
            int mid = left + (right -left) / 2;
            if (nums[mid] < target){
                left = mid + 1; // [mid + 1, right)是不确定的
            } else {
                right = mid; // [left, mid)是不确定的
            }
        }
        return right; // right所指向的位置就是元素出现的初始位置
    }

开区间(left, right)

原理差不多,就不一一画图了,需要修改:

  1. 左游标的初始位置-1,因为是开区间上面已经解释过,我们需要保证区间内的元素是没有被确定的,而区间外的元素已经都被确定完毕
  2. 右游标的初始位置arr.length
  3. 左游标更新的位置mid
  4. 右游标更新的位置mid
  5. 循环终止的条件left + 1 == right,此时区间内已经没有元素

代码部分

    public static int lower_bound(int[] nums, int target){
        int left = -1;
        int right = nums.length;
        while (left + 1 < right){ // 开区间内查找(left, right)
            int mid = left + (right -left) / 2;
            if (nums[mid] < target){
                left = mid; // (mid, right)是不确定的
            } else {
                right = mid; // (left, mid)是不确定的
            }
            System.out.println(left + " " + right);
        }
        return right; // right所指向的位置就是元素出现的初始位置
    }

变式

通过上面最简单的查找元素的初始位置,我们可以转换为更多的变式:

  1. 找到元素的初始位置

    这就是查找到元素初始位置的情况,如果有mid指向的元素比target大,那么就不断缩小右区间

  2. 找到元素的结束位置

    这种情况我们可以转化为:找到比target大1的元素的初始位置,也就是 m i d ≥ t a r g e t + 1 mid \geq target+1 midtarget+1

  3. m i d ≤ t a r g e t mid \le target midtarget

    这种情况可以转化为找到 > t a r g e t >target >target的元素位置,然后-1

  4. m i d < t a r g e t mid < target mid<target

    这种情况可以转换为找到 ≥ t a r g e t \geq target target的元素的位置,然后-1

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

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

相关文章

玩转RabbitMQ声明队列交换机、消息转换器

♥️作者&#xff1a;小宋1021 &#x1f935;‍♂️个人主页&#xff1a;小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识&#xff0c;和大家一起努力呀&#xff01;&#xff01;&#xff01; &#x1f388;&#x1f388;加油&#xff01; 加油&#xff01…

中兴交换机三层配置

中兴交换机三层配置 目的&#xff1a;将1-10端口划分到3001vlan&#xff0c;11-20端口划分到3002vlan中去 客户端客户端IPvlan网关主机A88.88.1.1203001192.168.1.254主机B192.168.100.1303002192.168.100.254 1、通过Console线登录设备 **********************************…

导出导入Oracle数据库使用黑框命令方式exp、imp【亲测】

下载工具 根据自己数据库的版本下载&#xff0c;以v19为例&#xff1a; 下载基础包Basic Package和工具包Tools Package 两个压缩包中的文件夹一样&#xff0c;但内容不一样&#xff0c;将两个压缩包中的文件解压合并到一起 https://www.oracle.com/database/technologies/inst…

TLV解码 - 华为OD统一考试(E卷)

2024华为OD机试&#xff08;E卷D卷C卷&#xff09;最新题库【超值优惠】Java/Python/C合集 题目描述 TLV编码是按 [Tag Length Value] 格式进行编码的&#xff0c;一段码流中的信元用Tag标识&#xff0c;Tag在码流中唯一不重复&#xff0c;Length表示信元Value的长度&#xff…

Zotero(7.0.5)+123云盘同步空间+Z-library=无限存储文献pdf/epub电子书等资料

选择123云盘作为存储介质的原因 原因1&#xff1a; zotero个人免费空间大小&#xff1a;300M&#xff0c;如果zotero云端也保存文献pdf资料则远远不够 原因2&#xff1a; 百度网盘同步文件空间大小&#xff1a;1G123云盘同步文件空间大小&#xff1a;10G 第一台电脑实施步骤…

微服务--Gateway网关

在微服务架构中&#xff0c;Gateway&#xff08;网关&#xff09;是一个至关重要的组件&#xff0c;它扮演着多种关键角色&#xff0c;包括路由、负载均衡、安全控制、监控和日志记录等。 Gateway网关的作用 统一访问入口&#xff1a; Gateway作为微服务的统一入口&#xff0c…

DNF Decouple and Feedback Network for Seeing in the Dark

DNF: Decouple and Feedback Network for Seeing in the Dark 在深度学习领域&#xff0c;尤其是在低光照图像增强的应用中&#xff0c;RAW数据的独特属性展现出了巨大的潜力。然而&#xff0c;现有架构在单阶段和多阶段方法中都存在性能瓶颈。单阶段方法由于域歧义&#xff0c…

计算机网络 --- Socket 编程

序言 在上一篇文章中&#xff0c;我们介绍了 协议&#xff0c;协议就是一种约定&#xff0c;规范了双方通信需要遵循的规则、格式和流程&#xff0c;以确保信息能够被准确地传递、接收和理解。  在这篇文章中我们将介绍怎么进行跨网络数据传输&#xff0c;在这一过程中相信大家…

常⻅中间件漏洞(WebLogic)靶场

1.后台弱⼝令GetShell 启动环境 默认账号密码&#xff1a;weblogic/Oracle123 weblogic常⽤弱⼝令&#xff1a;https://cirt.net/passwords?criteriaweblogic 这⾥注意&#xff0c; 单个账号错误密码5次之后就会⾃动锁定。 172.16.1.51:7001/console/login/LoginForm.jsp …

视频剪辑软件排行榜前十名推荐!从入门到专业领域都有!

随着短视频的流行&#xff0c;视频剪辑已成为表达创意、分享故事、获取流量的重要工具。无论是专业视频制作人还是业余爱好者&#xff0c;选择一款合适的视频剪辑软件都至关重要。今天&#xff0c;我们就来盘点一下视频剪辑软件排行榜前十名&#xff0c;帮助你找到最适合自己的…

JavaScript是如何来的~~

文章目录 前言一、网络的诞生 ( The birth of the Web )二、Mosaic 浏览器三、Netscape 浏览器四、JavaScript的诞生 ~ 千呼万唤始出来总结 前言 例如&#xff1a;想要了解一门语言的发展历程&#xff0c;首先你得知道它是怎么来的&#xff0c;所以本文开篇介绍了网络的基本发…

【行为树】01-第一棵树

如何创建一个行为树 行为树,类似于状态机,无非是在正确的时间在正确的条件下调用回调的一种机制。 此外,我们将会交替使用__“callback"和"tick”__这两个词。 这些回调函数里发生的事情取决于你。 在这个教程系列中,大部分时间,Actions 只会在控制台上打印一…

中国土地利用覆盖和变化数据集(1980-2021)

该数据集通过融合森林资源清查数据和20种遥感土地利用产品&#xff0c;重建生成了1980-2015年中国森林覆盖数据集&#xff0c;空间分辨率为11公里。并且在此基础上进一步获得高精度森林覆被信息和土地利用覆盖数据集相融合&#xff0c;生成了中国1980-2021年土地利用覆盖和变化…

Minio上传url资源文件,文件内容不全的问题

遇到问题 使用minio-client时候上传文件为url链接时候&#xff0c;上传inputstream流出现了文件上传成功&#xff0c;但是文件内容缺失&#xff0c;无法正常打开&#xff01; 先看看基本的依赖和配置代码&#xff1a; pom.xml依赖 <!-- tika MIME检测机制 --><depen…

Android NestedScrollView+TabLayout+ViewPager+ 其它布局,ViewPager 不显示以及超出屏幕不显示问题

前言 此场景为 NestedScrollView 嵌套多个布局 &#xff0c;大致结构为 NestedScrollViewTabLayoutViewPagerfragment 其它View,如下图 &#xff0c; 一、ViewPager 设置高度才会显示内容问题 原因&#xff1a;NestedScrollView 计算高度先于 ViewPager 渲染前&#xff0c;所…

电商跨境电商商城系统/网上商城接口/电商数据接口详情

电商API接口背景&#xff1a;电商运营中&#xff0c;数据分析这项工作越来越重要&#xff0c;许多品牌方也越来越热衷去做电商数据分析。不过&#xff0c;全面的数据该如何获取呢&#xff0c;此时&#xff0c;电商数据接口的重要性便凸显出来了。 电商API数据接口主要有以下特…

go 读取excel

一、安装依赖 go get github.com/tealeg/xlsx二、main.go package mainimport "fmt" import "github.com/tealeg/xlsx"type Student struct {Name stringSex string }func (student Student) show() {fmt.Printf("Name:%s Sex:%s\r\n", stude…

OneNet平台替换腾讯云IOT平台(2024年6月)

文章目录 一、前言二、OneNet替换腾讯云IOT三、修改说明&#xff1a;STM32代码3.1 替换MQTT三元组&#xff08;常规操作&#xff09;3.2 修改上传的数据格式。 四、修改说明&#xff1a;服务器配置 一、前言 从2024年06月20日起&#xff0c; 新注册腾讯云物联网开发平台的用户…

浅谈人工智能技术,对社会经济变革的思考

原创 冰锋血骨 芯原创 2024年09月23日 15:44 北京 英国DeepMind公司研发的AlphaGo在2016年3月第一次战胜了围棋世界冠军韩国棋手李世石,人工智能(AI,Artificial Intelligence)第一次映入公众的视野。人工智能是什么?人工智能会想人一样思考吗?人工智能可以应用在哪些领域…

如何用AI论文生成工具撰写一篇高质量的成人教育毕业论文

撰写一篇高质量的成人教育毕业论文并不简单&#xff0c;它有一定的步骤和策略。锐智AI今天就总结了一些关键的步骤&#xff0c;希望对即将毕业的你顺利完成论文写作&#xff1a; 介绍之前简单说下锐智AI&#xff0c;它是一款集论文大纲生成、内容填充、文献引用、查重修改于一…