二分查找之红蓝二分查找

꒰˃͈꒵˂͈꒱ 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.mfbz.cn/a/187548.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

每日一题 1457. 二叉树中的伪回文路径(中等,DFS)

一句话&#xff0c;深度搜索所有路径&#xff0c;判断路径是否伪回文 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right clas…

AI 视频 | Stable Video Diffusion 来了!(附体验地址)

1. 介绍 11 月 21 日&#xff0c;Stability AI 推出了 Stable Video Diffusion&#xff0c;这是 Stability AI 的第一个基于图像模型 Stable Diffusion 的生成式视频基础模型。 目前 Stability AI 已经在 GitHub 上开源了 Stable Video Diffusion 的代码&#xff0c;在 Huggin…

基于springboot实现乒乓球预约管理系统项目【项目源码】

基于springboot实现乒乓球预约管理系统演示 系统的开发环境 浏览器&#xff1a;IE 8.1&#xff08;推荐6.0以上&#xff09; 开发使用语言&#xff1a;JAVA JDK版本&#xff1a;JDK_8 数据库管理系统软件&#xff1a;Mysql 运行平台&#xff1a;Windows 7 运行环境&#…

外贸分享|如何从外贸小白成长为大咖?这10件事值得你坚持做

外贸成功不是一朝一夕的事&#xff0c;而是需要有充分的准备和持续的努力。作为一位有着丰富经验的外贸人员&#xff0c;我总结了成功的秘诀&#xff0c;分享了一个优秀的外贸人应该做好的10项工作。 1 找不到客户怎么办&#xff1f; 有很多各种各样的原因值得思考&#xff1a…

机器学习-线性回归

线性模型是一类用于建模输入特征与输出之间线性关系的统计模型。这类模型的基本形式可以表示为&#xff1a; 其中&#xff1a; 是模型的输出&#xff08;目标变量&#xff09;。 是截距&#xff08;常数项&#xff0c;表示在所有输入特征都为零时的输出值&#xff09;。 是权重…

禁止指定电脑程序运行的2种方法

你可能要问了&#xff0c;为什么要禁止电脑程序运行呢&#xff0c;因为有的公司要净化公司的工作环境&#xff0c;防止某些刺头员工在公司电脑上瞎搞。也有部分家长&#xff0c;是为了防止自己家的孩子利用电脑乱下载东西。 今天就分享2种禁止指定电脑程序运行的方法&#xff1…

教你IDEA解决GIT冲突

前言 GIT基本上贯穿我们的开发生涯&#xff0c;之所以要使用git也是有很多优点的 &#x1f339;&#x1f339;&#x1f339;&#x1f339;&#x1f339;&#x1f339;&#x1f339;&#x1f339; 1.通俗易懂点&#xff0c;保存代码不丢失&#xff1a;防止因内存&#xff0c;操…

pulseaudio是如何测试出音频延迟的

通常专业的音频设备生产厂商都有专业的设备来测试精确的音频链路延时。 那么没有专业设备怎么测试出音频延迟呢?如下图,我们可以看到pulseaudio可以测试出硬件音频延迟。 那么,他是怎么测试出硬件延迟的呢?他的理论依据是什么呢?接下来我带大伙一起探索一下。 /*占位…

一篇文章让你入门python集合和字典

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 一、集合: 增加 add 删除 del 删除集合 discard(常用)删除集合中的元素 &#xff0c;删除一个不存在的元素不会报错 remove 删除一个不存在的元素会报错 pop随…

Spine深入学习 —— 数据

atlas数据的处理 作用 图集&#xff0c;描述了spine使用的图片信息。 结构 page 页块 页块包含了页图像名称, 以及加载和渲染图像的相关信息。 page1.pngsize: 640, 480format: RGBA8888filter: Linear, Linearrepeat: nonepma: truename: 首行为该页中的图像名称. 图片位…

【点云surface】Poisson表面重建

1 介绍 Poisson表面重建算法是一种用于从点云数据生成平滑曲面模型的算法。它基于Michael Kazhdan等人在2006年发表的论文《Poisson surface reconstruction》。该算法通过将点云数据转换为体素表示&#xff0c;并利用Poisson方程来重建曲面。 该算法的基本原理是将点云数据转…

python教程:正常shell与反弹shell

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 正常shell需要先在攻击端开机情况下开启程序,然后攻击端运行程序,才能连接 反弹shell,攻击端是服务端,被攻击端是客户端 正常shell,攻击端是客户端,被攻击端是服务端 反弹shell,先启用服务端,再启用客户端 反弹shell的好处…

2022年09月 Scratch(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 运行下列程序后,结果为120的是? A: B: C: D: 答案:C 本题考察阶乘知识,12345的结果为120. <

【Python自学】七个超强学习网站,你值得拥有!

学习Python最主要的还是要动手&#xff0c;去找一些自己感兴趣的脚本&#xff0c;代码去练习&#xff0c;练的越多&#xff0c;对于一些英语单词&#xff0c;特殊符号要比死记硬背要容易记得些。 以下这些网站&#xff0c;虽说不上全方位的满足你的需求&#xff0c;但是大部分也…

基于springboot实现高校食堂移动预约点餐系统【项目源码】

基于springboot实现高校食堂移动预约点餐系统演示 Java语言简介 Java是由SUN公司推出&#xff0c;该公司于2010年被oracle公司收购。Java本是印度尼西亚的一个叫做爪洼岛的英文名称&#xff0c;也因此得来java是一杯正冒着热气咖啡的标识。Java语言在移动互联网的大背景下具备…

城市NOA加速落地,景联文科技高质量数据标注助力感知系统升级

当前&#xff0c;自动驾驶技术的演进正在经历着从基础L2到L3过渡的重要阶段&#xff0c;其中NOA&#xff08;自动辅助导航驾驶&#xff09;扮演着至关重要的角色。城市NOA&#xff08;L2.9&#xff09;作为城市场景下的NOA&#xff0c;被看作是车企向更高阶自动驾驶迈进的必经之…

汽车业务增长乏力!又被法雷奥告上法庭,英伟达有点「难」

随着智能汽车进入「降本增效」的关键周期&#xff0c;对于上游产业链&#xff0c;尤其是芯片的影响也在持续发酵。 本周&#xff0c;英伟达发布截至2023年10月29日的第三季度财报数据&#xff0c;整体业务收入为181.2亿美元&#xff0c;比去年同期增长206%&#xff0c;比上一季…

OSG粒子系统与阴影-爆炸模拟(3)

爆炸模拟示例 爆炸模拟示例的代码如程序清单11-4 所示&#xff1a; /* 爆炸模拟示例 */ void explosion_11_4() {osg::ref_ptr<osgViewer::Viewer> viewer new osgViewer::Viewer();osg::ref_ptr<osg::GraphicsContext::Traits> traits new osg::GraphicsContex…

基于袋獾算法优化概率神经网络PNN的分类预测 - 附代码

基于袋獾算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于袋獾算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于袋獾优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

C语言,通过数组实现循环队列

实现循环队列最难的地方就在于如何判空和判满&#xff0c;只要解决了这两点循环队列的设计就没有问题。接下来我们将会使用数组来实现循环队列。 接下来&#xff0c;为了模拟实现一个容量为4的循环队列&#xff0c;我们创建一个容量为4 1 的数组。 接下来我们将会对这个数组…
最新文章