当前位置: 首页 > news >正文

LeetCode 35. 搜索插入位置:二分查找的经典应用

刷LeetCode时,二分查找是高频考点,而35题「搜索插入位置」更是二分查找的入门级经典——它不仅考察对二分查找核心逻辑的理解,还需要灵活处理“目标值不存在”的边界场景。今天就来拆解这道题的解题思路,一步步看懂代码背后的逻辑,吃透O(log n)时间复杂度的实现要点。

题目回顾

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

核心约束:必须使用时间复杂度为 O(log n) 的算法

这里要注意,题目明确给出“排序数组”,这是二分查找能够适用的前提——二分查找的核心就是利用“有序”特性,每次将查找范围缩小一半,从而实现对数级的时间复杂度,比暴力遍历(O(n))高效得多。

解题思路:二分查找的边界处理

二分查找的关键的是「定义查找区间」和「处理边界条件」,这道题的难点在于:当目标值不在数组中时,如何精准找到它的插入位置。

我们先明确核心思路:

  1. 定义左右指针,划定查找区间(本题采用「左闭右闭」区间,即left ≤ right时,区间内仍有元素可查找);

  2. 计算中间位置mid,通过比较target和nums[mid]的大小,缩小查找范围;

  3. 用一个变量ans记录“可能的插入位置”,默认值设为数组长度n(对应目标值比所有元素都大的情况);

  4. 当target ≤ nums[mid]时,说明目标值可能在mid左侧(或就是mid),此时更新ans为mid,并将右指针左移(right = mid - 1);

  5. 当target > nums[mid]时,说明目标值在mid右侧,将左指针右移(left = mid + 1);

  6. 循环结束后,ans即为目标值的索引(存在时)或插入位置(不存在时)。

代码逐行解析

给出的代码简洁高效,我们逐行拆解,看懂每一步的作用:

functionsearchInsert(nums:number[],target:number):number{constn=nums.length;letleft=0,right=n-1,ans=n;// 维护两个闭区间while(left<=right){letmid=(left+right)>>1;if(target<=nums[mid]){ans=mid;right=mid-1;}else{left=mid+1;}}returnans;};

1. 变量初始化

  • const n = nums.length;:记录数组长度,避免多次调用nums.length,提升效率;

  • let left = 0, right = n - 1;:定义左指针(指向数组起始位置)和右指针(指向数组末尾位置),确立「左闭右闭」的查找区间;

  • ans = n;:初始化插入位置为数组长度,这是一个“兜底”设置——当target比数组中所有元素都大时,插入位置就是数组末尾,即索引n。

2. 二分查找循环

while (left <= right):循环条件是左指针不大于右指针,这是「左闭右闭」区间的核心特征——当left == right时,区间内还有最后一个元素需要判断,避免遗漏。

3. 中间位置计算

let mid = (left + right) >> 1;:计算中间索引mid,这里用「右移1位」代替「除以2」,效率更高(二进制右移1位等价于整除2,且计算机处理位运算比除法更快)。

注意:也可以写成mid = Math.floor((left + right) / 2),两者效果一致,但右移写法更简洁高效。

4. 核心判断逻辑

这部分是整个算法的核心,负责缩小查找范围并更新插入位置:

  • if (target <= nums[mid])

如果目标值小于等于中间元素,说明目标值要么就是nums[mid],要么在mid的左侧区间。此时,我们将ans更新为mid(因为mid是当前可能的插入位置),然后将右指针right移到mid - 1,缩小查找范围到左半部分。

  • else

如果目标值大于中间元素,说明目标值在mid的右侧区间,此时不需要更新ans(因为当前mid不可能是插入位置),直接将左指针left移到mid + 1,缩小查找范围到右半部分。

5. 返回结果

return ans;:循环结束后,left会大于right,此时ans已经记录了目标值的索引(存在时)或正确的插入位置(不存在时)。

关键细节:为什么这样能找到插入位置?

很多人会疑惑,ans的更新逻辑为什么能精准定位插入位置?我们举两个例子理解:

  1. 示例1:nums = [1,3,5,6],target = 5(目标值存在)

循环过程中,当mid = 2(nums[mid] = 5),target <= nums[mid],ans更新为2,right = 1。之后循环结束,返回ans=2,正确。

  1. 示例2:nums = [1,3,5,6],target = 2(目标值不存在)
  • 初始left=0,right=3,ans=4;

  • mid=1(nums[mid]=3),target=2 <= 3,ans更新为1,right=0;

  • mid=0(nums[mid]=1),target=2 > 1,left=1;

  • 循环结束(left=1 > right=0),返回ans=1,即插入位置在1和3之间,正确。

本质上,ans始终记录着“当前最接近target且大于等于target的元素索引”,当循环结束时,这个索引就是插入位置(如果target不存在),或者就是target本身的索引(如果存在)。

总结

这道题的核心是「二分查找的边界处理」,重点掌握3点:

  • 「左闭右闭」区间的定义的循环条件(left <= right);

  • ans变量的作用——兜底插入位置,动态更新可能的插入点;

  • mid的计算方式(右移1位)和指针移动逻辑(缩小一半范围)。

二分查找的难点在于边界条件的处理,这道题作为入门题,能帮我们快速掌握二分查找的核心逻辑。记住:只要数组有序,就可以优先考虑二分查找,而「左闭右闭」区间是最容易理解和实现的方式之一。

http://www.cnnetsun.cn/news/1411095.html

相关文章:

  • Qwen-Image开源模型部署:RTX4090D镜像为Qwen-VL提供生产级GPU算力保障
  • STM32是哈佛还是冯·诺依曼?揭秘其改进型哈佛架构本质
  • 对于复杂任务规划(如多步推理),OpenClaw 采用了何种规划算法?是树搜索还是基于大模型的链式思考?
  • 手把手教你用Unidbg和Frida搞定某鱼App的x-sign签名(附完整Trace调试流程)
  • 百度地图API隐藏功能挖掘:用地点检索+IP定位打造无感权限申请页
  • translategemma-4b-it实战落地:与Notion API联动实现笔记截图自动翻译归档
  • SAP ABAP内表操作避坑指南:为什么现代开发不再推荐OCCURS 0和WITH HEADER LINE
  • 5步搞定麦橘超然Flux部署:离线AI绘画从此不求人
  • POSTGRESQL中ON CONFLICT的高级应用场景解析
  • 如何用一款工具解决教师80%的教材获取难题:tchMaterial-parser全解析
  • 基于LSDYNA模拟的SPH方法:双水射流与单水射流冲击混凝土视频录制对比分析
  • GeoServer图层安全加固实战:从基础认证到AuthKey鉴权
  • Windows下OpenClaw安装指南:对接Qwen3-32B模型接口
  • OpenClaw故障自愈:GLM-4.7-Flash自动诊断任务失败原因并尝试修复
  • 新手入门:NoSQL与Redis核心基础解析
  • Wan2.1-umt5模型压缩与量化实践:在低资源环境下的部署优化
  • 3步搞定:快速免费下载Webtoon漫画的终极解决方案
  • 3D点云标注终极指南:使用labelCloud快速生成高质量训练数据
  • AI修复老视频帧?超清画质增强扩展应用指南
  • 掌握3大核心技术:从零开始的gprMax全流程应用指南
  • RISC-V调试实战:手把手教你用GDB+OpenOCD调试SiFive HiFive1开发板
  • FLUX.1-dev效果实测:看看这个开源模型生成的图片有多真实
  • 别再死记硬背!用一道真题彻底搞懂Cache行位数怎么算(附直接映射/回写策略详解)
  • 告别Update轮询!用Unity新输入系统(Input System)重构你的FPS控制器(支持手柄/键鼠)
  • Python AI入门:从Hello World到图像分类
  • TensorFlow-v2.15环境搭建:无需复杂配置,镜像开箱即用,即刻开始编码
  • Qwen3-ASR-1.7B效果对比:在Mandarin-English Switching Test Set上准确率+31.6%
  • 软萌拆拆屋惊艳案例:婚纱复杂结构拆解图(蕾丝/珠片/衬裙分层)
  • 5分钟解锁付费墙:Bypass Paywalls Clean终极免费阅读指南
  • SSD1308 OLED驱动库:I²C接口128×64单色屏嵌入式实战指南