从零开始刷算法-二分-搜索插入位置
在刷算法题时,很多人对二分查找(Binary Search)不陌生,但实际在面试或者实战中,如何利用二分查找解决插入位置问题,却常常容易犯错。今天我们主要巩固昨天的内容,来看一个简单题 LeetCode 第 35 题 “搜索插入位置(Search Insert Position)”,并用 C++ 代码实现。
题目描述
给定一个升序排列的整数数组 nums 和一个目标值 target,请你在数组中找到目标值的索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
示例:
输入: nums = [1,3,5,6], target = 5
输出: 2输入: nums = [1,3,5,6], target = 2
输出: 1输入: nums = [1,3,5,6], target = 7
输出: 4
要求时间复杂度 O(log n),也就是自然想到使用二分查找。
思路分析
这道题其实就是寻找大于等于目标值的第一个元素的位置,也可以理解为lower bound(二分查找模板)。
具体思路:
-
定义两个指针
left和right分别指向数组两端。 -
使用二分法循环:
-
计算中点
mid = (left + right) / 2。 -
如果
nums[mid] < target,说明目标值在右侧,left = mid + 1。 -
否则说明目标值在左侧(包括 mid 本身),
right = mid - 1。
-
-
循环结束后,
left指向的就是目标值的插入位置。
小技巧:这里我们用的是闭区间 [left, right] 二分查找。
C++ 代码实现
#include <vector>
using namespace std;class Solution {// lower_bound:寻找大于等于 target 的第一个位置int lower_bound(vector<int>& nums, int target) {int left = 0;int right = nums.size() - 1;while (left <= right) {int mid = (left + right) / 2;if (nums[mid] < target) {left = mid + 1; // target 在右侧} else {right = mid - 1; // target 在左侧或就是 mid}}return left; // 循环结束后,left 就是插入位置}public:int searchInsert(vector<int>& nums, int target) {return lower_bound(nums, target);}
};
核心技巧总结
-
闭区间 vs 开区间:
-
本题采用
[left, right]闭区间模板。 -
left最终就是插入位置。
-
-
lower_bound 思想:
-
在排序数组中找到第一个不小于 target 的位置。
-
这也是 STL 中
std::lower_bound的原理。
-
-
时间复杂度:
-
二分查找的时间复杂度为 O(log n),符合题目要求。
-
扩展
-
1.如果题目要求找到最后一个小于等于 target 的位置,可以改成 upper bound 模板:
if (nums[mid] <= target)left = mid + 1; // 前面染成红色 elseright = mid - 1;// 这里对应最后就是返回left - 1了也就是最后一块红色
-
2.对于 最后一个小于等于 target 的位置:
-
让 target+1 做 lower_bound,然后返回
结果 - 1。参考上一节的内容:https://blog.csdn.net/m0_59624833/article/details/154658810?spm=1001.2014.3001.5501 -
这样不会破坏边界,逻辑也更清晰,代码可读性更好。
-
总结
-
这道题本质是查找插入位置,可以抽象为 lower bound。
-
核心是熟练掌握二分查找模板。
-
结合面试角度:二分查找不仅仅用于查找元素,也可以用来求最优解、最小值或最大值等问题。
