二分查找之红蓝二分查找

news2024/11/18 8:18:53

꒰˃͈꒵˂͈꒱ 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.coloradmin.cn/o/1252960.html

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

相关文章

Executors(线程池操作类)

一&#xff0c;常用方法 二&#xff0c;案例 package XianChengChildren;import java.util.concurrent.*;public class ThewadPoolTest1 {public static void main(String[] args) throws Exception { // ExecutorService pool new ThreadPoolExecutor(3,5,8, // …

中国开源年度报告.问卷篇第二轮抽奖来袭!

中国开源年度报告.问卷篇第二轮抽奖来袭&#xff01;填问卷&#xff0c;赢鼠标垫&#xff0c;共建未来&#xff01; 中国开源年度报告由开源社发起&#xff0c;旨在多维度、多方式、多协作地呈现国内开源的发展情况。今年&#xff0c;我们再次邀请您一同参与&#xff0c;成为这…

人工智能时代的内容写作

内容不再只是王道&#xff0c;正如俗话所说&#xff1a;它是一种流动的货币&#xff0c;推动了巨大的在线信息和影响力经济。 每个品牌都是一个故事&#xff0c;通过其服务和商品讲述自己。尽管如此&#xff0c;大多数客户还是会通过您的在线内容最了解您。 但随着我们进入人…

使用ETLCloud实现CDC实时数据集成:从MySQL到ClickHouse的实时数据同步

背景 在上一篇文章中体验了 ETLCloud 的离线数据迁移功能&#xff0c;就像大数据领域里有离线计算和实时计算&#xff0c; ETLCloud 还提供了基于 CDC &#xff08;Change Data Capture&#xff09;的实时数据集成功能&#xff1a;实时数据集成是指通过变化数据捕获技术&#…

3D建模对制造企业的价值

除非你在过去几年一直躲在岩石下,否则你可能听说过“3D 建模”和“3D 渲染”这些术语。 但为什么这项技术如此重要,尤其是对于产品制造公司而言? 简而言之,它减少了项目时间和成本。 这为制造商提供了更多的设计试验空间。 未能利用 3D 建模技术的公司很快就会落后于竞争对…

5.1每日一题(无穷级数敛散性的判断:莱布尼兹准则、p级数、绝对收敛、条件收敛、比较法/比较法的极限形式)

莱布尼兹准则&#xff1a;&#xff08;1&#xff09;单调递减&#xff1b;&#xff08;2&#xff09;极限 -> 0 绝对收敛&#xff1a;级数的绝对值收敛 条件收敛&#xff1a;级数的绝对值发散 p级数的次幂 <1 时发散 &#xff1b;>1时收敛

微信小程序文件预览和下载-文件系统

文件预览和下载 在下载之前&#xff0c;我们得先调用接口获取文件下载的url 然后通过wx.downloadFile将下载文件资源到本地 wx.downloadFile({url: res.data.url,success: function (res) {console.log(数据,res);} })tempFilePath就是临时临时文件路径。 通过wx.openDocume…

Kotlin学习——kt中的类,数据类 枚举类 密封类,以及对象

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…

【LeetCode 热题 HOT 100】题解笔记 —— Day01

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

spring boot整合Jasypt实现配置加密

文章目录 目录 文章目录 前言 一、Jasypt是什么&#xff1f; 二、使用步骤 1.引入 2.测试使用 3.结果 总结 前言 一、Jasypt是什么&#xff1f; Jasypt&#xff08;Java Simplified Encryption&#xff09;是一个Java库&#xff0c;提供了一种简单的加密解密方式&#xff0c…

【JVM系列】- 穿插·对象的实例化与直接内存

对象的实例化与直接内存 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大家一起学习成长&#xff01; 文章目录…

laravel实现发送邮件功能

Laravel提供了简单易用的邮件发送功能&#xff0c;使用SMTP、Mailgun、Sendmail等多种驱动程序&#xff0c;以及模板引擎将邮件内容进行渲染。 1.在项目目录.env配置email信息 MAIL_MAILERsmtp MAIL_HOSTsmtp.qq.com MAIL_PORT465 MAIL_FROM_ADDRESSuserqq.com MAIL_USERNAME…

二阶常系数非齐次线性方程

,是一个n次多项式。 &#xff08;1&#xff09; 设 是(1)的特解。 是一个待定多项式 求的一阶导数 (求导&#xff1a;一项不变&#xff0c;二项求导二项不变&#xff0c;一项求导) 求的二阶导数 将其代入方程一 不可能是零 公式(2) 第一种情况&#xff1a; 即不是特征方程的…

c语言:有关内存函数的模拟实现

memcpy函数&#xff1a; 功能&#xff1a; 复制任意类型的数据&#xff0c;存储到某一数组中。 代码模拟实现功能&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include <stdio.h> #include<assert.h> memcpy…

机器学习第14天:KNN近邻算法

☁️主页 Nowl &#x1f525;专栏《机器学习实战》 《机器学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 文章目录 介绍 实例 回归任务 缺点 实例 分类任务 如何选择最佳参数 结语 介绍 KNN算法的核心思想是&#xff1a;当我们要判断一个数据为哪一类时…

ZKP中的哈希函数

1. 引言 后续博客&#xff1a; 如何选择ZK-friendly 哈希函数&#xff1f; 当暴露在ZK空间中时&#xff0c;对于普通crypto工程师来说&#xff0c;通常只需很少的时间就可以偶然发现一些外来的哈希函数——很可能是Poseidon。本文&#xff0c;将介绍ZK中高效哈希函数的历史&…

怎么给数据库某个字段建立一个前缀索引

说明&#xff1a;SQL调优中重要的一个环节是建立索引&#xff0c;其中有一条是字段值过长字段应该建立前缀索引&#xff0c;即根据字段值的前几位建立索引&#xff0c;像数据库中的密码字段、UUID字段。 因为其随机性&#xff0c;其实根据前几位就可以锁定某一条记录了。前缀索…

css实现图片绕中心旋转,鼠标悬浮按钮炫酷展示

vue模板中代码 <div class"contentBox clearfix home"><div class"circle"><img class"in-circle" src"../../assets/img/in-circle.png" alt""><img class"out-circle" src"../../as…

python基于DETR(DEtection TRansformer)开发构建钢铁产业产品智能自动化检测识别系统

在前文中我们基于经典的YOLOv5开发构建了钢铁产业产品智能自动化检测识别系统&#xff0c;这里本文的主要目的是想要实践应用DETR这一端到端的检测模型来开发构建钢铁产业产品智能自动化检测识别系统。 DETR (DEtection TRansformer) 是一种基于Transformer架构的端到端目标检…

字符串转换成十进制整数

编程要求 输入一个以#结束的字符串&#xff0c;本题要求滤去所有的非十六进制字符&#xff08;不分大小写&#xff09;&#xff0c;组成一个新的表示十六进制数字的字符串&#xff0c;然后将其转换为十进制数后输出。如果在第一个十六进制字符之前存在字符“-”&#xff0c;则…