二分查找:手拿把掐!------Java代码实现

“没有天赋,那就不断重复.”

文章目录

  • 前言
    • 文章有误敬请斧正 不胜感恩!
    • 模板一:(最基本的)
        • **左闭右闭:** [left,right]
    • 模板二:
      • **左闭右开区间模板:**
      • 区间:左闭右开[left,right):
    • 模板三:
      • 开区间模板:
      • (left,right)
    • 循环不变量:
    • 二分查找易错点:
    • 做题经验:
    • 疑问及解答:
      • 我自己的一些问题:
      • ans:
  • 题目中的:>,>=,<,<=情况的判断:(难点)
      • 模板1:闭区间:找第一个>=targe的元素的下标
      • 模板2:左闭右开区间:
      • 模板3:开区间:
  • 总结


前言

二分真是个好东西,她总是让我在清醒与糊涂间徘徊.
为了加深自己的记忆和印象,特此梳理了之前学习时的md笔记,又找出来回顾了一遍.
今天分享给大家,有好的想法和建议可以在评论区讨论或者私信我.
那么话不多说.我们来进入今天的学习吧!


文章有误敬请斧正 不胜感恩!

提示:以下是本篇文章正文内容,

模板一:(最基本的)

左闭右闭: [left,right]
while(left<=right)
class Solution {public int search(int[] nums, int target) {int left=0;int right=nums.length-1;int mid;while(left<=right){mid=left+(right-left)/2;   //防止越界if(nums[mid]>target){right=mid-1;//更新右边界nums[mid]已经确定了不是要查找的值,所以不必包含mid所以right更新为mid-1;//接下来搜索的区间是[left,mid-1];如果写成mid可能就死循环了.} else if(nums[mid]<target){left=mid+1; //left同理     }if (nums[mid]==target){return mid;}    }return -1;}}

模板 #1 是二分查找的最基础和最基本的形式。这是一个标准的二分查找模板,大多数高中或大学会在他们第一次教学生计算机科学时使用。模板 #1 用于查找可以通过访问数组中的单个索引来确定的元素或条件。

初始条件:left = 0, right = length-1
终止:left > right
向左查找:right = mid-1
向右查找:left = mid+1

为什么要写成mid=left+(right-left)/2,而不是mid=(left+right)/2。
因为会溢出!!此时的溢出指的是,mid可能会超出该数据类型的最大值
我们假定一个数据类型

uint8           //数据范围0~255
uint8 left,right,mid;//假定
left = 200;
right = 250;//则left+right =450 > 255,此时已经溢出了
//0001 1100 0010 因为只能存储8位,实际1100 0010=194
mid = (left+right)/2;  //此时实际mid=194/2mid = left+(right-left)/2; //200+(250-200)/2 = 225
//此方法绝对不会溢出,最好写成这样

手打:

class Solution {public int search(int[] nums, int target) {int left=0;int right=nums.length-1;int mid;while(left<=right){mid=left+(right-left)/2;if(nums[mid]>target){right=mid-1;}else {left=mid+1;}if (nums[mid]==target){return mid;}    }return -1;}}

模板二:

左闭右开区间模板:

区间:左闭右开[left,right):

此时left=right在区间上不合法,所以

while(left<right)
class Solution {public int search(int[] nums, int target) {int left=0;int right=nums.length;//注意这一点因为右边是开区间所以right=nums.length时[left,right)  右边界还是从数组最后一项也就是nums.length-1开始的.int mid;while(left<right){mid=left+(right-left)/2;if(nums[mid]>target){right=mid;//由于if判断过了nums[mid]不符合题意,下一个搜索的左区间不包含mid 又因为右边是开区间 所以right=mid就可以了.}else if(nums[mid]<target){left=mid+1;}if (nums[mid]==target){return mid;}    }return -1;}}

模板三:

开区间模板:

(left,right)

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

循环不变量:

区间的定义决定了边界处理:

二分查找易错点:

什么时候写left<=right?什么时候写left<right?
if(nums[mid]>target){什么时候写right=mid-1?什么时候写right=mid?}

做题经验:

如果题目要求是问某个值在不在区间里,用左闭右闭区间(while l<= r),每个mid做大于、小于、等于三次判断,在等于时输出,循环结束未输出说明不在区间里;

如果题目要求“找到第一个大于/小于x的下标”,用左闭右开区间(while l < r),每个mid做大于、小于等于两次判断,不在循环体里输出,循环结束返回l或r(l=r,不要返回mid),就是所求下标。

疑问及解答:

我自己的一些问题:

1、为什么要有区间这个概念
2、为什么要确定右开还是右闭
3、中点怎么计算
4、中点防溢出怎么推导出来的
5、边界问题怎么处理
6、中点取偏左还是偏右

ans:

1、 因为二分查找的本质是在不断地变换区间里比较,并找到target
2、 因为在比较的过程中,会有一个对边界的处理,如果右边的边界参予比较就是闭,如果不参与就是开
3、 M - L = R - M 所以 M = (R + L ) /2
4、 L + (R - L)/2
5、 target < nums[mid]
当区间是右闭的时候,R参予比较的。M与target做了比较,再充当R时需要减1,所以新的 R = M - 1
当区间是右开的时候,R是不参予比较的。R = M
6、取偏左。当数组长度为 1 时,
nums = 【2】
L= 0, R = 1, M =1(右开后,取偏右)
因为 当区间是右开的时候,R是不参予比较,M永远都比较不出值

题目中的:>,>=,<,<=情况的判断:(难点)

模板1:闭区间:找第一个>=targe的元素的下标

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

模板2:左闭右开区间:

int left=0;
int right=nums.length;
int mid;
while(left<right){mid=left+(right-left)/2;if(nums[mid]>target){right=mid;}else if(nums[mid]<target){left=mid+1;}if(nums[mid]==target){return left;//return left或者right都可以;因为跳出循环的条件是left==right}return -1;
}

模板3:开区间:

int left=-1;
int right=nums.length;
int mid;
while(left+1<right){mid=left+(right-left)/2;if(nums[mid]>target){right=mid;}else if(nums[mid]<target){left=mid;}if(nums[mid]==target){return right;}return -1;
}//对于lower_bound3
1. 为什么left = -1int right = nums.size(),而不是left = 0int right = nums.size()-1?
答案:left = -1是为了mid能取到0。处理【8,8,8,8】 target=8的情况。nums.size()-1是为了mid能取到nums.size()。例如【7,7,7,7】 target=8的情况。
2. 为什么终止条件是left + 1 < right或者left + 1 != right?如果nums【mid】 >= target改变为nums【mid】 > target,终止条件应该变化吗?
答案:终止条件取决于nums【mid】 >= target,最终的答案的正确性与left和right的初始化值也有关。
3. start == nums.size() || nums【start】 != target是在处理哪些特殊情况?
答案:【7,7,7,7】 target=8 和 【3,4,6,7】 target = 5 
以上三个细节,环环相扣,例如【7,7,7,7】 target=8贯穿这三个细节。一定要自己输入例子,打印输出,慢慢理解这些细节,才算真正掌握了。就算我把这三个细节列出来,有时候也不一定就能理解,一定要自己从头到尾把细节扣一遍!!!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

在力扣游荡了也近一年了,看到各种天才,窥镜而自视,又弗如远甚.
像我这种没有天赋的人,二分都要研究好久的人,就只能靠不断地重复了.
“贯穿这三个细节。一定要自己输入例子,打印输出,慢慢理解这些细节,才算真正掌握了。就算我把这三个细节列出来,有时候也不一定就能理解,一定要自己从头到尾把细节扣一遍!!!”
以后再看到会不会觉得可笑.

今天的分享就到这里了,我们下篇文章再见.

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

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

相关文章

内衣内裤衣机什么牌子好?五款口碑爆棚王炸机型推荐

如今科技是越来越发展了&#xff0c;迷你洗衣机的功能也是越来越强大了&#xff0c;这样小户型的家庭甚是喜爱&#xff0c;不仅解决了清洗衣物的问题&#xff0c;还能让小型洗衣机在家中起到一定的装饰效果。在清洁衣物的污渍的同时&#xff0c;还能有效除去衣物上的各种细菌。…

upload-labs闯关攻略

pass-1 提前准备好的一个PHP木马&#xff0c;然后将后缀名改为jpg上传 然后在上传的过程中利用抓包&#xff0c;将抓取到的包里面的后缀jpg改为php如图所示&#xff0c;然后放行 接着我们去访问上传的图片信息&#xff0c;如下图所示就为成功 pass-2 提前准备好的一个PHP木马…

http连接处理(最新版)

分析http类及请求接收 基础 epoll epoll_create函数 #include <sys/epoll.h> int epoll_create(int size) 创建一个指示epoll内核事件表的文件描述符&#xff0c;该描述符将用作其他epoll系统调用的第一个参数&#xff0c;size不起作用。 epoll_ctl函数 #include …

紫光同创——PLL IP 的使用(Logos2)

本文档主要针对 Logos2 系列的 PLL 配置&#xff0c;至于 Logos 系列的 PLL&#xff0c;可以参考《PLLIP 的使用(Logos)》的文档。 一、PLL IP 介绍 1、PLL 基本配置模式 Basic Configurations PLL IP 是紫光同创基于 PLL 及时钟网络资源设计的 IP&#xff0c;通过不同的参数配…

牛客周赛 Round 58(ABCDF)

目录 A.会赢吗&#xff1f; B.能做到的吧 C.会赢的&#xff01; D.好好好数 F.随机化游戏时间 A.会赢吗&#xff1f; 思路&#xff1a; 签到题&#xff0c;比大小 void solve() {double a,b;cin>>a>>b;if(a>b) cout<<"NO";else cout<&…

ByteTrack多目标跟踪(一)—理论基础

ByteTrack多目标跟踪 算法概述 github: https://github.com/ifzhang/ByteTrack ByteTrack是一种基于Tracking-by-Detection范式的多目标跟踪算法。 先前的多目标追踪算法一般在完成当前帧的目标检测后只会保留置信度比较大的检测框用于进行目标跟踪&#xff0c;比如图中置信度…

思维导图在线制作怎么制作?5个软件教你快速进行思维导图制作

思维导图在线制作怎么制作&#xff1f;5个软件教你快速进行思维导图制作 思维导图是一种用于组织信息、梳理思路和激发创意的可视化工具。在线制作思维导图可以帮助你随时随地进行创作和分享&#xff0c;以下是五款在线思维导图工具&#xff0c;可以帮助你快速进行思维导图的制…

828华为云征文|基于华为云Flexus云服务器X搭建FTP服务器

❀目录 ❀概述❀特点❀环境准备❀安装❀配置文件修改❀创建目录、修改权限❀控制台安全组开启21端口❀工具验证❀总结 ❀概述 FTP文件传输协议是一种在网络中进行文件传输的广泛使用的标准协议。作为网络通信中的基础工具&#xff0c;FTP允许用户通过客户端软件与服务器进行交…

Java技术栈 —— Spark入门(二)之实时WordCount

Java技术栈 —— Spark入门&#xff08;二&#xff09; 一、kafka1.1 创建topic1.2 准备input与查看output 二、spark2.1 spark下的程序文件2.2 用spark-submit提交作业 参考文章&#xff1a; 参考文章或视频链接[1] 《Kafka Spark Stream实时WordCount》 实验环境&#xff…

【AQS源码】深入理解AQS的工作原理

【AQS源码】深入理解AQS的工作原理-CSDN博客

从零开始掌握容器技术:Docker的奇妙世界

容器技术在当今的云计算和软件开发领域中扮演着越来越重要的角色。如果你是一名计算机专业的学生或从事IT行业的从业者&#xff0c;可能已经听说过Docker这个词。它在软件开发、部署、运维等环节中大放异彩&#xff0c;但对于刚接触这个概念的朋友来说&#xff0c;可能还是有些…

JMeter在Mac下的安装使用

前言 开发过程中需要对系统进行性能测试&#xff0c;可以选用jemter对接口进行压测&#xff0c;jemter优点如下&#xff1a; 开源许可证&#xff1a;Jmeter完全免费&#xff0c;允许开发者使用源代码进行开发 友好的 GUI&#xff1a;Jmeter 非常易于使用&#xff0c;不需要花…

flume 使用 exec 采集容器日志,转储磁盘

flume 使用 exec 采集容器日志&#xff0c;转储磁盘 在该场景下&#xff0c;docker 服务为superset&#xff0c;flume 的sources 选择 exec &#xff0c; sinks选择 file roll 。 任务配置 具体配置文件如下&#xff1a; #simple.conf: A single-node Flume configuration#…

推荐4个一键生成 PPT的AI工具,让你畅享智能办公!

对于职场人士来说&#xff0c;ai PPT 工具已经成为了高效办公的一大得力助手 。它可以让你从繁琐的 PPT 制作中解脱出来&#xff0c;把更多的时间放在其他的工作准备上面。并且它们有极大的设计能力&#xff0c;会让我们的PPT变的设计感十足&#xff0c;如果大家正在为PPT制作烦…

js逆向——RSA实战案例讲解

受害者网站&#xff1a;http://www.15yunmall.com/pc/login/index 检查超时&#xff0c;这个我们不管他 直接分析参数&#xff0c;有2处加密位置&#xff0c;分别为password和csrftoken 只要是能够跟栈的&#xff0c;一律先在send的位置下断 很快就跟栈找到加密数据的位置 R…

《JavaEE进阶》----4.<SpringMVC①简介、基本操作(各种postman请求)>

本篇博客讲解 MVC思想、及Spring MVC&#xff08;是对MVC思想的一种实现&#xff09;。 Spring MVC的基本操作、学习了六个注解 RestController注解 RequestMappering注解 RequestParam注解 RequestBody注解 PathVariable注解 RequestPart注解 MVC View(视图) 指在应⽤程序中…

我用 GPT 学占星

最近对占星赶兴趣&#xff0c;但是看到星盘中好多名词&#xff0c;不懂是什么意思&#xff1f;所以直接问 gpt &#xff0c; 发现回答的真的很棒&#x1f389; &#xff01; 假如我想知道各个状态的具体是根据什么数据来显示的&#xff1f; 分分钟解决了我的问题&#xff1b; 我…

docker Desktop报错 error pulling image configuration 处理

问题描述 在 docker 拉数据 出现以下错误 error pulling image configurarion&#xff1a; 这个问题 主要是 可能应该某些原因不能网络无法连上镜像 原因分析&#xff1a; 1。 2024年 5月以后 国内很多IP都 。。。懂的都懂&#xff0c;很多 VPN 也是。。。 懂的都懂&#x…

7种常见排序

1 直接插入排序 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中&#xff0c;直到所有的记录插入完为 止&#xff0c;得到一个新的有序序列 。 void InsertSort(int* a, int n) {for (int i 0; i < n - 1; i){//划分区间【0&#xff0c;end】int en…

Ubuntu 24.04 安装 英特尔工具包 Intel® Toolkits

目录 1.采用用户界面 GUI 安装英特尔基本工具包 Intel oneAPI Base Toolkit 1.1 下载离线英特尔基本工具包 1.2 安装英特尔基本工具包 1.3 英特尔基本工具包 Intel oneAPI Base Toolkit 环境设置 2.安装英特尔高性能计算工具包 Intel HPC Toolkit 2.1 下载离线英特尔高性…