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


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

相关推荐
huangdong_1 小时前
拼多多商品图片视频批量采集:整店自动分类与高清原图
前端·javascript·音视频
胡萝卜术1 小时前
从零开始掌握AI应用开发:我的大模型学习路线图(RAG/Agent/MCP/全栈实践)
前端·javascript·面试
YAwu111 小时前
从 TodoList 看 React + TypeScript 类型实践
前端·javascript
8Qi81 小时前
LeetCode 188 & 123:股票买卖问题(限制交易次数)—— 联合题解
算法·leetcode·职场和发展·动态规划
To_OC1 小时前
折腾两天 HTTP 接口调用,终于把 fetch 和前后端分离从书本概念落地到实操了
javascript·node.js·全栈
KaMeidebaby1 小时前
卡梅德生物技术快报|细胞周期检测抗原流式分析:参数调试、软件拟合与问题排查
网络·人工智能·python·网络协议·tcp/ip·算法·机器学习
一只齐刘海的猫1 小时前
【Leetcode】三数之和
数据结构·算法·leetcode
lightqjx1 小时前
【算法】数据结构_扩展域并查集
数据结构·算法·并查集·扩展域并查集
无忧.芙桃1 小时前
debug实例与分析(一)
开发语言·c++·算法