LeetCode35. 搜索插入位置:二分查找的基础与细节

今天我们来拆解 LeetCode 热题 100 中的第 35 题「搜索插入位置」,这道题是二分查找的入门经典,也是很多算法面试的高频考点,非常适合用来理解二分查找的核心逻辑与边界处理。


题目描述

给定一个无重复元素的升序数组 nums 和一个目标值 target,要求:

  1. 若 target 存在于数组中,返回其索引;
  2. 若不存在,返回它按升序插入数组后的位置索引;
  3. 必须实现时间复杂度为 O (log n) 的算法。

示例:

  • 输入:nums = [1,3,5,6], target = 5 → 输出:2(找到目标值,直接返回索引)
  • 输入:nums = [1,3,5,6], target = 2 → 输出:1(插入到元素 3 的前面)
  • 输入:nums = [1,3,5,6], target = 7 → 输出:4(插入到数组末尾)

解题思路:二分查找的核心逻辑

这道题的本质是在有序数组中找到第一个大于等于 target 的位置 ,也就是算法中常说的 lower_bound 问题。二分查找的优势在于,每次可以将问题规模减半,将时间复杂度从暴力遍历的 O (n) 优化到 O (log n)。

关键细节

  1. 指针初始化 :左指针 left 指向数组开头,右指针 right 指向数组末尾,形成闭区间 [left, right]。

  2. 中间位置计算 :使用 left + Math.floor((right - left) / 2) 而非 (left + right) / 2,避免数组长度过大时出现数值溢出问题。

  3. 区间收缩逻辑:

    • 若 nums[mid] == target:直接返回 mid,找到目标值;
    • 若 nums[mid] < target:目标值在右侧区间,更新 left = mid + 1;
    • 若 nums[mid] > target:目标值在左侧区间,更新 right = mid - 1。
  4. 循环结束处理 :当 left > right 时循环结束,此时 left 就是目标值的插入位置,因为它指向第一个大于 target 的元素索引。


代码实现(JavaScript)

javascript

运行

ini 复制代码
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    let left = 0;
    let right = nums.length - 1;

    while (left <= right) {
        // 防止溢出,等价于 Math.floor((left + right) / 2)
        const mid = Math.floor(left + (right - left) / 2);
        if (nums[mid] === target) {
            // 找到目标值,直接返回索引
            return mid;
        } else if (nums[mid] < target) {
            // 目标值更大,去右边找
            left = mid + 1;
        } else {
            // 目标值更小,去左边找
            right = mid - 1;
        }
    }

    // 没找到,left 就是插入位置
    return left;
};

复杂度分析

  • 时间复杂度:O (log n),每次循环将问题规模减半,最多循环 log₂n 次;
  • 空间复杂度:O (1),仅使用常数级别的额外空间。

常见误区与优化

很多同学写这道题时,容易在循环条件和指针更新上出错:

  1. 错误地使用 left < right 作为循环条件,导致边界处理逻辑复杂;
  2. 中间位置直接写 (left + right) / 2,忽略了数值溢出的风险;
  3. 循环结束后不知道该返回 left 还是 right,这也是二分查找的经典易错点。

其实只要理解了 "循环结束时 left 一定指向第一个大于等于 target 的位置",这个问题就迎刃而解了。


这道题虽然简单,但二分查找的思想在很多算法题中都有延伸,比如查找重复元素的左右边界、旋转有序数组的最小值等。掌握好这道题,能帮你打下扎实的二分查找基础。

相关推荐
启观川8 分钟前
数据结构与算法 -第 3 章 常用算法-回溯算法
数据结构·笔记·python·算法
w2sfot12 分钟前
AI时代,JS加密还有效吗?
开发语言·前端·javascript
零基础12313 分钟前
LLM4AD:面向算法设计的大语言模型智能体框架
人工智能·算法·语言模型
haluhalu.26 分钟前
Agent = LLM + 上下文 + 工具(含观察 / 动作空间、ReAct 循环)
前端·javascript·人工智能·python·react.js·机器学习·个人开发
子兮曰6 小时前
把 649 种文件格式塞进一个网页里:一个「文件不出浏览器」的预览器
前端·javascript·后端
启观川9 小时前
数据结构与算法 -第 3 章 常用算法-动态规划
数据结构·笔记·python·算法
码爸9 小时前
排序算法介绍
python·算法·排序算法
paopaokaka_luck9 小时前
基于springboot+vue的智慧家政管理系统(AI问答、 WebSocket实时沟通、ECharts运营分析、订单规则与服务追踪)
java·javascript·spring boot·数据分析·echarts·mybatis
溪语流沙10 小时前
【每天一个CSS | Day19】流光文字与一笔写成的手写签名
前端·javascript·css
动词ing10 小时前
【题目练习】算法 组合总和||
算法