二分搜索的三种方法

news2024/11/16 6:57:22

首先总的说一下二分搜索。如果区间具有二分性,这个二分性不仅仅是指区间是有序的,而是我们可以通过某一种性质将整个区间分成左区间和右区间。我们通过二分的方法去不断缩小查找的区间,最终让区间内没有元素,这个时候的我们就得到了分界的边界。

二分问题的难点在于边界的处理,整不好就死循环了,所以我们面对二分问题要一步一步分析,不要漏掉东西。

这里有两个原则大家要记住:

1)我们的最终目的就是让搜索区间没有一个元素;

2)left 的左面全都是<target的,right 的右面全都是>=target的(注意,这里的<,>=不是一定的,根据我们自己定的条件为主)。

这两个在这里不懂没关系,继续往下看就明白了。

一.全闭区间

即我们的查找区间的闭区间的,这个选择也影响到了我们的循环终止条件。我们的最终目的就是让区间没有一个元素,两面都是闭的,我们必须要 l<=r 。为什么?闭区间要想没有元素,要让 l 与 r 错开才行。

//闭区间
int n=nums.length;
int left=0;
int right=n-1;

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

可能有的问题:

1.left和right的初始值为什么是这个?

left和right的初始值是根据我们区间的开闭写的。如果左面是开区间,left=-1,闭区间,left=0;右面同理,开区间,right=n,闭区间right=n-1。

2.那我们这么写的最终left和right分别指的下标是什么?

left 的左面全都是<target的,right 的右面全都是>=target的。所以说left指的是第一个>=target的元素,right指的是最后一个<target的元素。

3.为什么left要等于mid+1,为什么不能等于mid,right也是为什么不能等于mid?

还是刚刚的那句:left 的左面全都是<target的,right 的右面全都是>=target的。比如我们已经知道了 nums[mid]<target 了,所以说mid下标的元素一定<target,left的左面都是<target的,所以left直接等于mid+1就保证了left左面全都<target。right同理。

二.半闭半开

也是大家经常在网上看到的模板的类型,本人并不推荐这种写法,+1不+1的,可能在做什么模板题的时候觉得自我良好。但是二分是一种用于优化的算法,一般不会单独出现,在一些复杂的问题其实就很乱了。

上面是一些题外话,下面才是正题。

半闭半开有两种情况:左闭右开和左开右闭。

//左闭右开
int n=nums.length;
int left=0;
int right=n;

while(left<right){
    int mid=left+(right-left)/2;
    if(nums[mid]<target){
        left=mid+1;
    }else{
        right=mid;
    }
}
//左开右闭
int n=nums.length;
int left=-1;
int right=n-1;

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

可能有的问题:

1.为什么上面left和right两次不同?

开的那一部分是取不到的,所以说我们就要多“往外”一点,因为一开始要全部元素都在搜索区间里。

2.为什么两种情况left和right这个+1那个-1的?

我们在上一种全闭的情况时提到:left 的左面全都是<target的,right 的右面全都是>=target的。这里就拿左闭右开举例。右面是开区间,也就是说right指向的下标的元素不在我们的搜索区间内,所以说已经满足了right 的右面全都是>=target的这个条件。我们此时说mid下标的这个元素>=target的,如果是闭区间,right要-1,但是根据开区间的性质,我们是取不到这个mid下标的元素的,可以理解成无形的减了一,我们就没必要再-1了,直接让right=mid就行了。但是left是闭的,所以要+1才能保证left 的左面全都是<target的。

左开右闭同理。

3.为什么在左开右闭时求mid要+1?

这个也是开区间影响的。在最后只剩下两个元素的时候,我们求mid,mid一定是指向左面的下标的,但是左面是开区间,也就是说左面的元素不在搜索区间内,不在区间怎么能判断呢?所以我们mid要+1。

4.结束时,left指向什么,right指向什么?

最终left和right会重合,所以这里说left或right都一样。

唉?为什么会重合?

因为这是一开一闭。我们最用要的是:left 的左面全都是<target的,right 的右面全都是>=target的。以左闭右开为例。比如说left和right重合的时候在t下标处,t下标对于的元素是>=target的(这是一定的),左区间是必的,所以left左面全都是<target的成立,右区间是开的,取不到t,所以right 的右面全都是>=target的。

明白上面的我们就知道left和right会指向第一个>=target的元素。

左开右闭的left和right会指向最后一个<target的元素。

三.全开区间

这是本人最推荐的一种方法,这种方法没有了+1-1的问题,方便记忆。

int n=nums.length;
int left=-1;
int right=n;

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

简洁明了。

可能有的问题:

1.循环条件为什么是left+1<right?

还是那句话:我们的最终目的就是让搜索区间没有一个元素。其实当left+1=right的时候区间内就没有一个元素了对不对,所以说这个时候就要终止了。

2.left为什么不用+1,right为什么不用-1?

大家如果看懂上面关于这方面的解释的话这个自己就明白了。一句话:因为这是全开的。

3.结束时,left指向什么,right指向什么?

left指向最后一个<target的元素,right指向第一个>=target的元素。

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

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

相关文章

清华大学提出基于ESKF的松耦合里程计RINO:一种具有非迭代估计的精确、稳健的雷达惯性里程计

Abstract 精确的定位和建图对于实现自动驾驶车辆的自主导航至关重要。然而&#xff0c;当GNSS信号失效或在极端天气条件&#xff08;例如雾、雨和雪&#xff09;下&#xff0c;车体运动估计仍然面临重大挑战。近年来&#xff0c;扫描雷达因其较强的穿透能力成为一种有效的解决…

微信小程序之路由跳转传数据及接收

跳转并传id或者对象 1.home/index.wxml <!--点击goto方法 将spu_id传过去--> <view class"item" bind:tap"goto" data-id"{{item.spu_id}}"> 结果: 2.home/index.js goto(event){// 路由跳转页面,并把id传传过去//获取商品idlet i…

tensorflow案例6--基于VGG16的猫狗识别(准确率99.8%+),以及tqdm、train_on_batch的简介

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 本次还是学习API和如何搭建神经网络为主&#xff0c;这一次用VGG16去对猫狗分类&#xff0c;效果还是很好的&#xff0c;达到了99.8% 文章目录 1、tqdm…

海康大华宇视视频平台EasyCVR私有化视频平台服务器选购主要参数有哪些?

在构建现代服务器和视频监控系统时&#xff0c;选择合适的硬件配置和关键技术是确保系统性能和稳定性的基础。服务器选购涉及到多个关键参数&#xff0c;这些参数直接影响到服务器的处理能力、数据存储、网络通信等多个方面。 同时&#xff0c;随着视频监控技术的发展&#xf…

Redisson的可重入锁

初始状态&#xff1a; 表示系统或资源在没有线程持有锁的情况下的状态&#xff0c;任何线程都可以尝试获取锁。 线程 1 获得锁&#xff1a; 线程 1 首次获取了锁并进入受保护的代码区域。 线程 1 再次请求锁&#xff1a; 在持有锁的情况下&#xff0c;线程 1 再次请求锁&a…

Java-01 深入浅出 MyBatis - MyBatis 概念 ORM映射关系 常见ORM 详细发展历史

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…

C语言第13节:指针(3)

1. 回调函数 回调函数的基本思想是&#xff0c;将函数指针作为参数传递给另一个函数&#xff0c;并在需要时通过这个函数指针调用对应的函数。这种方式允许一个函数对执行的内容进行控制&#xff0c;而不需要知道具体的实现细节。 回调函数在以下场景中尤为有用&#xff1a; …

Tensorflow基本概念

简介&#xff1a;本文从Graph讲到Session&#xff0c;同时讲解了tf.constant创建tensor的用法和variable需要初始化的知识点&#xff0c;可以给你打好一个学习Tensorflow的基础。本文都是基于TensorFlow1.14.0的版本下运行。 本专栏将会系统的讲解TensorFlow在1.14.0版本下的各…

【包教包会】CocosCreator3.x框架——带翻页特效的场景切换

一、效果演示 二、如何获取 1、https://gitee.com/szrpf/TurnPage 2 2、解压&#xff0c;导入cocos creator&#xff08;版本3.8.2&#xff09;&#xff0c;可以直接运行Demo演示 三、算法思路 1、单场景 页面预制体 通过loadScene来切换页面&#xff0c;无法实现页面特效…

【MySQL 保姆级教学】事务的自动提交和手动提交(重点)--上(13)

目录 1. 什么是事务&#xff1f;2. 事务的版本支持3. 事务提交的方式3.1 事务提交方式的分类3.2 演示的准备的工作3.2.1 创建表3.2.2 MySQL的服务端和客户端3.2.3 调低事务的隔离级别 4. 手动提交4.1 手动提交的命令说明4.2 示例一4.3 示例二4.4 示例三4.5 示例四 5. 自动提交5…

几何合理的分片段感知的3D分子生成 FragGen - 评测

FragGen 来源于 2024 年 3 月 25 日 预印本的文章&#xff0c;文章题目是 Deep Geometry Handling and Fragment-wise Molecular 3D Graph Generation&#xff0c; 作者是 Odin Zhang&#xff0c;侯廷军&#xff0c;浙江大学药学院。FragGen 是一个基于分子片段的 3D 分子生成模…

数据结构笔记(其八)--一般树的存储及其遍历

1.知识总览 一般的树会有多个孩子&#xff0c;所以存储结构也会与二叉树略有不同。 一般树的遍历。 2.双亲表示法 双亲表示法&#xff0c;也是父亲表示法&#xff0c;即每个节点中都存储了其父节点的地址信息。 特性&#xff1a;可以轻易地找到父节点&#xff0c;但寻找孩子节…

Linux系统Centos设置开机默认root用户

目录 一. 教程 二. 部分第三方工具配置也无效 一. 教程 使用 Linux 安装Centos系统的小伙伴大概都知道&#xff0c;我们进入系统后&#xff0c;通常都是自己设置的普通用户身份&#xff0c;而不是 root 超级管理员用户&#xff0c;导致我们在操作文件夹时往往爆出没有权限&am…

医院信息化与智能化系统(21)

医院信息化与智能化系统(21) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应…

【论文阅读】利用SEM二维图像表征黏土矿物三维结构

导言 在油气储层研究中&#xff0c;黏土矿物对流体流动的影响需要在微观尺度上理解&#xff0c;但传统的二维SEM图像难以完整地表征三维孔隙结构。常规的三维成像技术如FIB-SEM&#xff08;聚焦离子束扫描电子显微镜&#xff09;虽然可以获取高精度的3D图像&#xff0c;但成本…

Yocto - 使用Yocto开发嵌入式Linux系统_13 创建定制层

Creating Custom Layers 除了使用社区或供应商提供的现有图层外&#xff0c;我们还将在本章中学习如何为我们的产品创建图层。此外&#xff0c;我们还将了解如何创建机器定义和分布&#xff0c;并从中获益&#xff0c;从而更好地组织我们的源代码。 In addition to using exist…

每日八股——JVM组成

直接上图 JVM&#xff08;Java虚拟机&#xff09;是运行Java字节码的虚拟机。它主要由以下几个部分组成&#xff1a; 1. 类加载器&#xff08;ClassLoader&#xff09; 负责加载class文件到内存中&#xff0c;并生成对应的Class对象。类加载器分为启动类加载器、扩展类加载器…

JavaScript 中的 undefined 、null 与 NaN :概念解析与对比

文章目录 &#x1f4af;前言&#x1f4af;undefined1. 什么是 undefined2. undefined 的使用场景3. undefined 的特性 &#x1f4af;null1. 什么是 null2. null 的使用场景3. null 的特性 &#x1f4af;NaN1. 什么是 NaN2. NaN 的使用场景3. NaN 的特性 &#x1f4af;三者的区别…

计算机网络学习笔记-3.3以太网和局域网

以太网 以太网&#xff08;Ethernet&#xff09;是一种用于计算机网络的技术规范&#xff0c;广泛应用于局域网&#xff08;LAN&#xff09;的构建。它定义了如何在网络设备之间传输数据&#xff0c;并确保这些数据能够被可靠传送。以太网是目前最常见和最广泛使用的局域网技术…

Linux篇(用户管理命令)

目录 一、用户与用户组 1. 为什么要做用户与用户组管理 2. Linux的用户及用户组 2.1. Linux的多用户多任务 2.2. 什么是用户 2.3. 什么是用户组 2.4. 用户和用户组的关系 二、用户和用户组管理 1. 用户组管理 1.1. 用户组添加 /etc/group文件结构 1.2. 用户组修改 …