2026/5/21 15:47:26
网站建设
项目流程
购物网站首页源码,广告设计专业专升本考什么,网站怎么提升实用性,网站开发有前途详细解释可以看这篇文章https://www.cnblogs.com/labuladong/p/12320448.html。
一、基础框架#xff1a;二分查找通用模板
给出二分查找的核心框架#xff0c;明确关键可变细节#xff08;用...标记#xff09;#xff0c;并强调“用else if替代else”以清晰展现逻辑二分查找通用模板给出二分查找的核心框架明确关键可变细节用...标记并强调“用else if替代else”以清晰展现逻辑intbinarySearch(int[]nums,inttarget){intleft0,right...;// 细节1right初始化while(...){// 细节2循环终止条件intmid(leftright)/2;if(nums[mid]target){...}// 细节3找到目标后的处理elseif(nums[mid]target){left...}// 细节4左边界更新elseif(nums[mid]target){right...}// 细节5右边界更新}return...;// 细节6最终返回值}注暂忽略mid计算的溢出问题提及可参考前文解决。二、三类典型场景细节拆解与逻辑分析网页分三类场景逐一解析“right初始化、循环条件、边界更新、返回值”等细节的差异及原因核心是围绕“搜索区间定义”展开逻辑推导。1. 场景1寻找一个数基本二分搜索功能搜索目标值存在则返回索引否则返回-1。核心代码intbinarySearch(int[]nums,inttarget){intleft0;intrightnums.length-1;// 搜索区间[left, right]两端闭while(leftright){// 终止条件left right 1区间为空无遗漏intmid(leftright)/2;if(nums[mid]target)returnmid;// 找到即返回仅需一个目标elseif(nums[mid]target)leftmid1;// 排除mid新区间[mid1, right]elseif(nums[mid]target)rightmid-1;// 排除mid新区间[left, mid-1]}return-1;// 区间为空未找到}关键细节解释为何while(left right)因搜索区间是[left, right]终止时区间为空如[3,2]无遗漏若用终止时区间为[left, left]非空可能漏掉目标。为何leftmid1/rightmid-1因mid已验证非目标需从搜索区间中排除。缺陷无法找到目标的“左侧边界”或“右侧边界”如[1,2,2,2,3]中target2无法返回索引1或3。实例输入数组 nums [1, 3, 5, 7, 9, 11]目标值 target 7若目标不存在target 4预期返回 - 1分步推导以找 7 为例初始化搜索区间 [left, right] [0, 5]闭区间覆盖所有元素第一次循环mid (05)/2 2nums[2] 5因 5 7排除左半区mid 已验证非目标更新 left mid1 3新区间 [3,5]第二次循环mid (35)/2 4nums[4] 9因 9 7排除右半区更新 right mid-1 3新区间 [3,3]第三次循环满足 left right33mid 3nums[3] 7找到目标直接返回 mid 3符合预期若目标不存在找 4初始区间 [0,5]第一次循环 mid254right1区间 [0,1]第二次循环 mid014left1区间 [1,1]第三次循环 mid134left2区间 [2,1]空区间循环终止返回 -1符合预期2. 场景2寻找左侧边界如target2返回最左索引1功能找到目标值的最左侧索引若无则返回-1返回值也可理解为“小于target的元素个数”。核心代码intleft_bound(int[]nums,inttarget){if(nums.length0)return-1;intleft0;intrightnums.length;// 搜索区间[left, right)左闭右开while(leftright){// 终止条件left right区间为空无遗漏intmid(leftright)/2;if(nums[mid]target)rightmid;// 不返回收缩右边界锁定左侧elseif(nums[mid]target)leftmid1;// 新区间[mid1, right)elseif(nums[mid]target)rightmid;// 新区间[left, mid)}// 补全“未找到”判断left范围是[0, nums.length]if(leftnums.length)return-1;// target比所有数大returnnums[left]target?left:-1;// 验证是否为目标}关键细节解释为何right nums.length因搜索区间是[left, right)right取nums.length可覆盖“target比所有数大”的场景如返回4表示小于target的元素有4个。为何while(left right)终止时leftright区间[left, left)为空无遗漏。为何nums[mid]target时rightmid不立即返回而是缩小右边界在[left, mid)中继续搜索锁定最左侧目标。为何返回left终止时leftright二者等价。3. 场景3寻找右侧边界如target2返回最右索引3功能找到目标值的最右侧索引若无则返回-1。核心代码intright_bound(int[]nums,inttarget){if(nums.length0)return-1;intleft0,rightnums.length;// 搜索区间[left, right)左闭右开while(leftright){intmid(leftright)/2;if(nums[mid]target)leftmid1;// 不返回收缩左边界锁定右侧elseif(nums[mid]target)leftmid1;// 新区间[mid1, right)elseif(nums[mid]target)rightmid;// 新区间[left, mid)}// 补全“未找到”判断left范围是[0, nums.length]if(left0)return-1;// target比所有数小returnnums[left-1]target?(left-1):-1;// 需减1因left已超右侧边界}关键细节解释为何nums[mid]target时leftmid1不立即返回缩小左边界在[mid1, right)中继续搜索锁定最右侧目标。为何返回left-1因left更新为mid1终止时nums[left]必非目标而nums[left-1]可能是目标如[1,2,2,2,3]中找到最后一个2后left会指向4需减1得3。三、核心总结细节差异的因果逻辑三类场景的细节差异本质由“搜索区间定义”决定形成如下因果链场景搜索区间right初始化while循环条件找到target后的操作边界更新方式返回值处理寻找一个数[left, right]nums.length - 1left right立即返回midleftmid1/rightmid-1未找到返回-1寻找左侧边界[left, right)nums.lengthleft rightrightmid收缩右边界leftmid1/rightmid未找到返回-1找到返回left寻找右侧边界[left, right)nums.lengthleft rightleftmid1收缩左边界leftmid1/rightmid未找到返回-1找到返回left-1实例解析与代码验证二分查找的“细节魔鬼”体现在搜索区间定义上不同场景对应不同的区间逻辑。以下通过「具体需求输入输出分步推导」为三种场景逐一举例帮你直观理解边界处理的本质。场景1寻找一个数基本二分搜索核心需求在有序无重复/有重复数组中判断目标值是否存在存在则返回任意一个目标值的索引不存在则返回-1仅需“找到与否”不关心目标的位置范围。实例输入数组nums [1, 3, 5, 7, 9, 11]目标值target 7若目标不存在target 4预期返回-1分步推导以找7为例初始化搜索区间[left, right] [0, 5]闭区间覆盖所有元素第一次循环mid (05)/2 2nums[2] 5因5 7排除左半区mid已验证非目标更新left mid1 3新区间[3,5]第二次循环mid (35)/2 4nums[4] 9因9 7排除右半区更新right mid-1 3新区间[3,3]第三次循环满足left right33mid 3nums[3] 7找到目标直接返回mid 3符合预期若目标不存在找4初始区间[0,5]第一次循环mid254right1区间[0,1]第二次循环mid014left1区间[1,1]第三次循环mid134left2区间[2,1]空区间循环终止返回-1符合预期场景2寻找左侧边界核心需求在有序有重复数组中找到目标值的「最左侧索引」即第一个等于目标的元素位置若目标不存在返回-1需“锁定目标的起始范围”如统计目标出现次数时需先找左边界。实例输入数组nums [1, 2, 2, 2, 3, 4]目标值target 2若目标不存在target 5预期返回-1分步推导以找2的左边界为例初始化搜索区间[left, right) [0, 6)左闭右开right取数组长度覆盖“目标比所有数大”的场景第一次循环mid (06)/2 3nums[3] 2找到目标但不返回需收缩右边界锁定左半区更新right mid 3新区间[0,3)第二次循环mid (03)/2 1nums[1] 2继续收缩右边界更新right mid 1新区间[0,1)第三次循环mid (01)/2 0nums[0] 1因1 2排除左半区更新left mid1 1新区间[1,1)空区间验证返回left 1nums[1] 2返回1即2的最左侧索引符合预期若目标不存在找5初始区间[0,6)第一次循环mid325left4区间[4,6)第二次循环mid545left6区间[6,6)空区间验证返回left 6等于数组长度返回-1符合预期场景3寻找右侧边界核心需求在有序有重复数组中找到目标值的「最右侧索引」即最后一个等于目标的元素位置若目标不存在返回-1与左边界配合可计算目标出现次数右边界 - 左边界 1。实例输入数组nums [1, 2, 2, 2, 3, 4]目标值target 2若目标不存在target 0预期返回-1分步推导以找2的右边界为例初始化搜索区间[left, right) [0, 6)左闭右开同左边界场景第一次循环mid (06)/2 3nums[3] 2找到目标但不返回需收缩左边界锁定右半区更新left mid1 4新区间[4,6)第二次循环mid (46)/2 5nums[5] 4因4 2排除右半区更新right mid 5新区间[4,5)第三次循环mid (45)/2 4nums[4] 3因3 2排除右半区更新right mid 4新区间[4,4)空区间验证返回left 4需检查left-1 3因left已超右边界nums[3] 2返回3即2的最右侧索引符合预期若目标不存在找0初始区间[0,6)第一次循环mid320right3区间[0,3)第二次循环mid120right1区间[0,1)第三次循环mid010right0区间[0,0)空区间验证返回left 0等于0返回-1符合预期三种场景实例对比总结场景实例输入目标值预期输出核心差异实例中体现寻找一个数[1,3,5,7,9,11]73找到目标立即返回区间是闭区间[left, right]寻找左侧边界[1,2,2,2,3,4]21找到目标不返回收缩右边界返回left寻找右侧边界[1,2,2,2,3,4]23找到目标不返回收缩左边界返回left-1