LeetCode 35 题「搜索插入位置」是二分查找的经典入门变种题,其核心并非简单的 "找目标值",而是求有序数组中第一个大于等于 target 的位置(也称为二分查找的 "下界")。本文从题目分析、核心原理、代码实现到拓展延伸,帮你彻底掌握这一高频考点。
一、题目回顾
题目描述
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。要求:时间复杂度必须为 O(logn)。

二、核心原理:二分查找 "下界" 的逻辑
1. 为什么用二分查找?
题目要求时间复杂度 O(logn),而有序数组的二分查找恰好满足这一要求(顺序查找为 O(n),不符合要求)。
2. 二分 "下界" 的核心逻辑
我们维护一个闭区间 [left, right],通过不断缩小区间找到目标位置:
- 初始化:
left = 0,right = nums.size() - 1(覆盖整个数组); - 循环条件:
left <= right(闭区间有效时继续查找); - 缩小区间规则:
- 若
nums[mid] == target:直接返回mid(找到目标值,其位置就是下界); - 若
target > nums[mid]:说明下界在右半区间,更新left = mid + 1; - 若
target < nums[mid]:说明下界在左半区间,更新right = mid - 1;
- 若
- 循环终止:当
left > right时,left恰好是第一个≥target 的位置(下界)。
3. 关键:为什么循环结束返回 left?
循环终止时 left > right,此时:
right是最后一个小于 target 的位置;left是第一个大于等于 target 的位置;这是二分查找求下界的 "固定结论",无需额外计算,直接返回left即可
三、完整代码实现
迭代版(工程首选)
cpp
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
// 闭区间 [left, right] 二分查找
while (left <= right) {
// 计算mid:避免 (left+right)/2 整数溢出
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid; // 找到目标值,直接返回
} else if (target > nums[mid]) {
left = mid + 1; // 下界在右半区间
} else {
right = mid - 1; // 下界在左半区间
}
}
// 循环结束,left 是第一个≥target的位置
return left;
}
};
递归版(理解逻辑用)
递归版更直观体现 "分治思想",核心逻辑与迭代版一致:
cpp
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
return binarySearch(nums, target, 0, nums.size() - 1);
}
private:
int binarySearch(vector<int>& nums, int target, int left, int right) {
// 递归终止条件:返回下界 left
if (left > right) return left;
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (target > nums[mid]) {
// 递归查找右半区间
return binarySearch(nums, target, mid + 1, right);
} else {
// 递归查找左半区间
return binarySearch(nums, target, left, mid - 1);
}
}
};