二分查找之红蓝二分查找

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱
ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如需转载还请通知˶⍤⃝˶
个人主页:xiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客
系列专栏:xiaoxie的算法系列专栏——CSDN博客●'ᴗ'σσணღ*
我的目标:"团团等我💪( ◡̀_◡́ ҂)" 

( ⸝⸝⸝›ᴥ‹⸝⸝⸝ )欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​+关注(互三必回)!

目录

 一.二分查找

 1.说明

2.二分查找的模板

1.普通二分查找模板:

2.寻找左边界的二分查找模板

3. 寻找右边界的二分查找模板

4. 二分查找变体模板1(寻找第一个满足条件的值):

5. 二分查找变体模板2(寻找最后一个满足条件的值):

6. 旋转数组的二分查找模板:

3.红蓝二分查找法

1. 

 

df1a6ad258684edd8bd72c937b3984c3.jpeg

 一.二分查找

 1.说明

相信有很多读者都认为二分查找法就是一个非常简单的算法,没有什么技术含量,博主想说的是二分查找本身的思想确实十分简单,当它奇妙的就是在它的边界确定条件上,相信大家在写二分查找的时候经常在边境确定的时候出现问题导致结果出现误差。

2.二分查找的模板

此外,目前二分查找主流的有六套模板。博主把它们归纳总结了一下

1.普通二分查找模板:

public int binarySearch(int[] nums, int target) {int left = 0, right = nums.length - 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;  // 未找到目标值
}

2.寻找左边界的二分查找模板

public int leftBound(int[] nums, int target) {int left = 0, right = nums.length;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;  // 目标值在右半部分} else {right = mid;  // 目标值在左半部分}}return left;  // 返回左边界索引
}

3. 寻找右边界的二分查找模板

public int rightBound(int[] nums, int target) {int left = 0, right = nums.length;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] <= target) {left = mid + 1;  // 目标值在右半部分} else {right = mid;  // 目标值在左半部分}}return left - 1;  // 返回右边界索引
}

4. 二分查找变体模板1(寻找第一个满足条件的值):

public int firstPosition(int[] nums, int target) {int left = 0, right = nums.length - 1;while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;  // 目标值在右半部分} else {right = mid;  // 目标值在左半部分}}return nums[left] == target ? left : -1;  // 返回第一个满足条件的值的索引
}

5. 二分查找变体模板2(寻找最后一个满足条件的值):

public int lastPosition(int[] nums, int target) {int left = 0, right = nums.length - 1;while (left < right) {int mid = left + (right - left + 1) / 2;if (nums[mid] > target) {right = mid - 1;  // 目标值在左半部分} else {left = mid;  // 目标值在右半部分}}return nums[left] == target ? left : -1;  // 返回最后一个满足条件的值的索引
}

6. 旋转数组的二分查找模板:

public int searchRotated(int[] nums, int target) {int left = 0, right = nums.length - 1;while (left <= right) {int mid = left + (right - left) / 2;if (nums[mid] == target) {return mid;  // 找到目标值,返回索引}if (nums[left] <= nums[mid]) {if (nums[left] <= target && target < nums[mid]) {right = mid - 1;  // 目标值在左半部分} else {left = mid + 1;  // 目标值在右半部分}} else {if (nums[mid] < target && target <= nums[right]) {left = mid + 1;  // 目标值在右半部分} else {right = mid - 1;  // 目标值在左半部分}}}return -1;  // 未找到目标值
}

以上就是目前主流的一些二分查找的模板,当然如果大家对二分查找有着深刻了解,也可以自己创建出一些二分查找的模板,只有你能理解二分法这一思想,再加上对边界的判断我相信你对二分查找法应该没什么问题

3.红蓝二分查找法

1. 说明

博主介绍的红蓝二分查找法和普通二分查找法不同的是

这套模板和常规的模板存在不一样: 主体思路:L 指针掌管左边蓝色区域, R指针掌管右边红色区域,两者互不冲突,通过不断向目标元素靠近扩大掌管区域,直到两者掌管区域接壤,即 l+1==r  时终止。

ec9c196bdb0b4ab9b704f5068f889a4b.png

 2.模板

//简代码
int L = 0;
int R = nums.length;
while(L+1 < R) {int M = (L+R)/2//如果数字大时可以使用 M = L +(R-L)/2;if (isblue(m)) {L = M;} else {R = M ;}
} return L/R //根据实际情况情况选择 

3.详细讲解

开始时,L指针和 R指针取在搜索区间界外,L=首个元素下标−1,R=末尾元素下标+1,此时所有元素均未着色;
循环条件始终为 L+1 < R,当 L=R 时跳出循环,此时蓝红区域划分完成,所有元素均已着色;
M指针取值始终为 M =(L+R)/2
L指针和 R指针变化的时候直接变为 M指针,即对 M 指针所指向元素进行染色,无需 +1 或者−1;
本模板唯一变化的地方是判断目标元素最终落在左边蓝色区域还是右边红色区域。以不变应万变,根据情况的不同,变换判断条件,大大的降低了出错的可能。以下还有一些我们需要注意到的说明

1.根据target的情况 < 、≤在左边蓝色区域找,≥ 、>在右边红色区域找

2.染色完成后的特殊情况:如果遍历完成后都为蓝色区域的话左边红色区域长度为 0 ,如果搜索目标位于左边红色区域,则搜索结果不存在,同理都为红色区域右边蓝色区域长度为 0 ,如果搜索目标位于右边蓝色区域,则搜索结果不存在一般需要后期处理。

3.普通技巧: 以下技巧必须掌握: 排序 二分查找的运用是建立在数组有序的基础上的,如果数组无序,我们要先对数组进行排序,如果数组有多个维度,我们针对需要二分查找的维度进行排序。 构造二分查找区间 当问题能够转化为区间内二分判定问题的时候,构造搜索区间,在蓝红二分法中设L指针初始为L0;R指针设为二分查找结束后L指针始终为Lt,R指针始终为Rt,target在(Lt--Rt)之间双指针 L 和 R 始终对目标元素 targettargettarget 进行夹逼,这是一条非常重要的性质。 如果开始构造搜索区间没有思路的时候,直接用题目提示中的数值区间!如果开始构造搜索区间没有思路的时候,直接用题目提示中的数值区间

4. 高阶技巧: 缩进边界构造区间 在第④条中,我们讨论了全蓝或者全红的特殊状态,其实我们可以提前判断,根据题意:

搜索区间第一个元素颜色待定,搜索区间最后一个元素颜色待定,L=首个元素下标−1,R=末尾元素下标+1,如区间为[0, n−1]则L=-1,R=N;

搜索区间第一个元素最终一定为蓝色,搜索区间最后一个元素颜色待定,L=首个元素下标,R=末尾元素下标+1,如区间为[0, n−1]则L=0,R=N;

搜索区间第一个元素颜色待定,搜索区间最后一个元素最终一定为红色L=首个元素下标−1,R=末尾元素下标,如区间为[0, n−1]则L=-1,R=N-1;

搜索区间第一个元素最终一定为蓝色,搜索区间最后一个元素一定为红色L=首个元素下标−1,R=末尾元素下标+1,如区间为[0, n−1]则L=-1,R=N;

4.实战演示

如力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

ca3a1a1acfaa4c69bbea5670d3b3d185.png

class Solution {public int searchRangeLeft(int[] nums, int target) {int left = -1;int right =nums.length;while (left+1 != right) {int mid = (left + right) / 2;if(nums[mid] <= target) {left = mid;}else {right = mid;}}return left;}public int searchRangeRight(int[] nums, int target) {int left = -1;int right =nums.length;while (left+1 != right) {int mid = (left + right) / 2;if(nums[mid] < target) {left = mid;}else {right = mid;}}return right;}public int[] searchRange(int[] nums, int target) {int leftIndex = searchRangeLeft(nums,target);int rightIndex = searchRangeRight(nums,target);if(leftIndex >= rightIndex && leftIndex < nums.length && nums[leftIndex] == target && nums[rightIndex] == target) {return new int[] {rightIndex,leftIndex};}return new int[] {-1,-1};}
}

以上就是我使用该模板的解决的一道题,读者有兴趣也可以去尝试一下,链接如下

34. 在排序数组中查找元素的第一个和最后一个位置

以上就是关于蓝红二分查找法的模板和内容了,当然如果你比较熟悉二分查找法的思想也可以自己做一个模板。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙原生应用/元服务开发-AGC分发如何上架HarmonyOS应用

一、上架整体流程 二、上架HarmonyOS应用 获取到HarmonyOS应用软件包后&#xff0c;开发者可将应用提交至AGC申请上架。上架成功后&#xff0c;用户即可在华为应用市场搜索获取开发者的HarmonyOS应用。 配置应用信息 1.登录AppGallery Connect&#xff0c;选择“我的应用”。…

CCC联盟——UWB MAC(二)

在上一篇文章中对CCC联盟UWB MAC框架进行了介绍&#xff0c;在本文中&#xff0c;将MAC层的时间网格进行简单介绍。 2、MAC时间网格&#xff08;Time Grid) DK UWB测距协议属于一对多&#xff08;One to Many, O2M)测距协议。发起者&#xff0c;每次发送4帧&#xff0c;接收N帧…

学习Pandas 二(Pandas缺失值处理、数据离散化、合并、交叉表与透视表、分组与聚合)

文章目录 六、高级处理-缺失值处理6.1 检查是否有缺失值6.2 缺失值处理6.3 不是缺失值NaN&#xff0c;有默认标记的 七、高级处理-数据离散化7.1 什么是数据的离散化7.2 为什么要离散化7.3 如何实现数据的离散化 八、高级处理-合并8.1 pc.concat实现合并&#xff0c;按方向进行…

Linux:Ubuntu虚拟机安装详解:VMware下的逐步指南

目录 1. centOS系统 2. ubuntu系统 1. 下载Ubuntu映像 step1 step2 step3 2. 新建虚拟机 step1 step2 Step3 step4 step5 step6 内存 内核 映像 显示 网络 3. 网络配置 NAT模式 本机IP获取 ​编辑 bridge模式 4. 开启虚拟机 5. 虚拟机常用配置 语言 …

为什么,word文件在只读模式下,仍然能编辑?

Word文档设置了只读模式&#xff0c;是可以编辑的&#xff0c;但是当我们进行保存的时候就会发现&#xff0c;word提示需要重命名并选择新路径才能够保存。 这种操作&#xff0c;即使可以编辑文字&#xff0c;但是原文件是不会受到影响的&#xff0c;编辑之后的word文件会保存到…

Redis Stream消息队列

什么是Stream? Stream 实际上是一个具有消息发布/订阅功能的组件&#xff0c;也就常说的消息队列。其实这种类似于 broker/consumer(生产者/消费者)的数据结构很常见&#xff0c;比如 RabbitMQ 消息中间件、Celery 消息中间件&#xff0c;以及 Kafka 分布式消息系统等&#x…

openEuler20.03学习01-创建虚拟机

赶个时髦&#xff0c;开始学习openEuler 20.03 (LTS-SP3) 操作系统iso下载地址&#xff1a;https://repo.openeuler.openatom.cn/openEuler-20.03-LTS-SP3/ISO/x86_64/openEuler-20.03-LTS-SP3-x86_64-dvd.iso 公司有现成的vmware环境&#xff0c;创建虚拟机i测试&#xff0c…

qgis添加arcgis的mapserver

左侧浏览器-ArcGIS地图服务器-右键-新建连接 Folder: / 展开-双击图层即可

通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示(三)

通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示(三) 不使用base64编码方式传递 #include <ros/ros.h> #include <signal.h> #include <sensor_msgs/Image.h> #include <message_filters/subscriber.h> #include <message_filter…

leetcode中“辅助栈”类题目和“单调栈”类题目的异同

1 总结 1 栈中元素的特性 2 单调栈存在一次性连续删除多个栈顶的情况&#xff0c;但是普通的栈&#xff0c;一次只pop掉一个栈顶元素 2 LC1209. 删除字符串中的所有相邻重复项 II - 普通辅助栈 class Solution {public String removeDuplicates(String s, int k) {int ns.l…

mysql忘记密码,然后重置

数据库版本8.0.26 只针对以下情况 mysql忘记了密码&#xff0c;但是你navicat之前连接上了 解决方法&#xff1a; 第一步&#xff0c;选中mysql这个数据库&#xff0c;点击新建查询 第二步&#xff1a;重置密码 alter user rootlocalhost IDENTIFIED BY 你的密码; 然后就可…

随机生成字母

目录 css代码 html代码 js代码 css代码 .box {width: 400px;height: 400px;background-color: #797979;margin: 100px auto;padding-top: 100px;}.text{width: 200px;height: 50px;outline: none;border: 5px solid #545454;background-color: #797979;border-radius: 10px;f…