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 的位置",这个问题就迎刃而解了。


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

相关推荐
张元清7 分钟前
React useResizeObserver Hook:追踪元素尺寸变化(2026)
javascript·react.js
战族狼魂2 小时前
高频面试题精选:分治与AI Agent架构
人工智能·算法·大模型·大语言模型
李剑一2 小时前
你用过网易的将军令嘛?它底层实现账号保护的原理相当简单粗暴
算法
Scott9999HH2 小时前
告别流量波动玄学!从法拉第电磁定律到底层 C/C++ 流量累积算法,深度解密工业级电磁流量计选型与开发
c语言·c++·算法
瑞瑞小同学3 小时前
处理echarts x轴内容过多,重叠问题
前端·javascript·echarts
香辣牛肉饭3 小时前
【算法】动态规划 最长公共子序列(LCS)
经验分享·笔记·算法·动态规划
像我这样帅的人丶你还4 小时前
MCP + npm:给五年前的老系统接上AI
前端·javascript·agent
.徐十三.4 小时前
一篇文章看到最短路径——Dijkstra算法
算法
科学实验家5 小时前
二叉树的几道题
算法