尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

高频必考!二分查找:边界条件总写错?一个模板搞定所有变种

高频必考!二分查找:边界条件总写错?一个模板搞定所有变种 LeetCode 704「二分查找」题目短得只有几行但面试手写时翻车率极高while left right还是right mid - 1还是midmid (leftright)//2会不会溢出有重复元素时怎么找边界更关键的是二分查找不止用来找元素——大厂面试最爱考「二分答案」在值域上二分把“最优化问题”转化为“判定问题”。现在不只给你一个能跑通的代码而是给你一套“左闭右闭”万能模板从此所有二分变体通杀。再附送“二分答案”的思维框架让你面试时直接拔高一个档次。 题目速览30 秒读懂在有序无重复数组nums中找到target的下标不存在返回 -1。示例nums [-1,0,3,5,9,12],target9→ 返回4示例target2→ 返回-1 核心思路每次砍掉一半O(log n)是怎样炼成的暴力为什么慢线性扫描一个个比O(n)。如果数组长度是10⁹比如数据库索引线性扫描就炸了。有序数组的“作弊”优势你可以直接看中间元素如果nums[mid] target→ 找到如果nums[mid] target→ 目标一定在右半边因为左边都更小如果nums[mid] target→ 目标一定在左半边每次都能扔掉一半搜索范围从n → n/2 → n/4 → … → 1步数 ≈ log₂(n)。n10⁹ 时只需要 30 次比较️ 图解全过程手把手走一遍以nums [-1, 0, 3, 5, 9, 12],target 9步骤leftrightmidnums[mid]比较动作1052339left32354999✅ 返回 4仅 2 步再试target2步骤leftrightmidnums[mid]比较动作1052332right12010-1-12left13111002left2421———leftright → -1区间从 6 → 3 → 1 → 0完美收敛。 代码实现Python 版左闭右闭强烈推荐classSolution:defsearch(self, nums: List[int], target: int)- int:left, right 0, len(nums) -1# 闭区间 [left, right]whileleft right:# 区间非空mid left (right - left) //2# 防溢出ifnums[mid] target:returnmidelifnums[mid] target:left mid 1# 排除 midelse:right mid -1# 排除 midreturn-1Java 版classSolution{publicintsearch(int[] nums,inttarget){intleft 0, right nums.length -1;while(left right) {intmid left (right - left) /2;if(nums[mid] target)returnmid;elseif(nums[mid] target) left mid 1;elseright mid -1;}return-1;}}⚠️防坑三定律循环条件是闭区间是开区间。统一用逻辑最清晰。边界更新既然mid已经比较过就要mid1或mid-1否则死循环。溢出防护mid left (right-left)//2永远比(leftright)//2安全尤其 Java/C。⏱️ 复杂度分析面试必问时间O(log n)每次减半空间O(1)仅常数变量 举一反三4 道高频变种题一个模板通杀题目变化点模板调整LeetCode 34. 找第一个和最后一个位置有重复元素找边界两次二分找左边界target时收缩右边界和右边界target时收缩左边界LeetCode 33. 搜索旋转排序数组数组在某个点旋转先判断mid落在哪一段有序区间再决定收缩方向LeetCode 153. 寻找旋转排序数组最小值找最小值比较nums[mid]和nums[right]决定最小值在左还是右LeetCode 410. 分割数组的最大值二分答案不二分数组下标而是二分“最大段和”的值域用判定函数 check(limit) 面试追问模拟提前准备惊艳全场Q1为什么要用left (right-left)//2而不是(leftright)//2防止整数溢出。当left和right都接近INT_MAX时leftright会溢出变成负数导致 mid 计算错误。left (right-left)/2永远安全。Q2如果数组有重复元素标准二分找到的是哪个位置标准二分不保证它可能返回任意一个等于 target 的下标。要找到第一个或最后一个需要修改判断条件找左边界当nums[mid] target时right mid - 1最后left就是第一个。找右边界当nums[mid] target时left mid 1最后right就是最后一个。Q3“二分答案”和普通二分有什么区别普通二分是在数组下标上二分依赖数组有序。二分答案是在答案的值域上二分依赖“单调性”如果某个值可行那么比它更大或更小的值也可行。比如“最大最小化”问题可以用二分答案 贪心判定。 实战小技巧刷题党必备模板固定死记左闭右闭模板所有变种都基于此修改判定条件。记忆口诀左闭右闭更新mid±1防溢用减法。调试技巧如果死循环检查边界更新是否遗漏±1如果漏解检查循环条件是否用了。 实际应用场景不止是刷题数据库索引B树叶子节点内用二分查找定位记录版本控制系统Git 的git bisect二分查找引入 bug 的提交调试定位在上百个版本中快速定位问题版本算法竞赛二分答案解决“最大化最小值”“最小化最大值”类问题 今日思考题给定一个排序数组找target的第一个出现位置不存在返回 -1。你能基于上面的左闭右闭模板写出只改判断条件的代码吗提示当nums[mid] target时不急着返回继续收缩右边界。
返回列表