3.3 二分查找专题: LeetCode 35. 搜索插入位置
1. 题目链接
LeetCode 35. 搜索插入位置
2. 题目描述
给定一个升序排列的整数数组 nums 和一个目标值 target,要求:
- 若 target存在于数组中,返回其索引。
- 若不存在,返回其应插入的位置,使得插入后数组仍保持有序。
示例:
- 输入:nums = [1,3,5,6], target = 5→ 输出:2
- 输入:nums = [1,3,5,6], target = 2→ 输出:1
3. 示例分析
- 目标存在: 
  - nums = [1,3,5,6], target = 5,直接返回索引- 2。
 
- 目标不存在: 
  - nums = [1,3,5,6], target = 2,插入到索引- 1,数组变为- [1,2,3,5,6]。
 
4. 算法思路
二分查找法:
- 初始化指针:left = 0,right = nums.size() - 1。
- 循环缩小范围: 
  - 计算中间索引 mid = left + (right - left) / 2(防止整数溢出)。
- 若 nums[mid] < target,目标在右半区间,调整left = mid + 1。
- 若 nums[mid] ≥ target,目标在左半区间或等于当前值,调整right = mid。
 
- 计算中间索引 
- 终止条件:当 left == right时,检查nums[left]与target的关系:- 若 nums[left] < target,返回left + 1。
- 否则,返回 left。
 
- 若 
5. 边界条件与注意事项
- 空数组处理:用户代码未显式处理空数组,若 nums为空,访问nums[left]会导致越界错误。需增加:if (nums.empty()) return 0;
- 目标值大于所有元素:循环结束后 left指向末尾,nums[left] < target时返回left + 1,正确。
- 重复元素:返回第一个匹配或插入位置(符合题意)。
6. 代码实现
class Solution 
{
public:
    int searchInsert(vector<int>& nums, int target) 
    {
        if (nums.empty()) return 0;
        int left = 0, right = nums.size() - 1;
        while(left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] < target) left = mid + 1;
            else right = mid;
          
        }
        if(nums[left] < target) return left + 1; 
        return left;
    }
};

暴力枚举法与二分查找法对比图表
| 对比维度 | 暴力枚举法 | 二分查找法 | 
|---|---|---|
| 核心思想 | 遍历数组,找到第一个大于等于 target的位置。 | 利用有序性,每次将搜索范围缩小一半,定位插入位置。 | 
| 时间复杂度 | O(n)(遍历所有元素)。 | O(log n)(每次缩小一半范围)。 | 
| 空间复杂度 | O(1)(无需额外存储)。 | O(1)(仅需常数变量记录指针)。 | 
| 实现方式 | 单层循环逐个比较元素。 | 循环调整左右指针,计算中间索引。 | 
| 适用场景 | 无序数组、极小数据规模(n ≤ 100)。 | 有序数组、大规模数据(n ≥ 1e6)。 | 
| 优点 | 实现简单,不依赖数组有序性。 | 时间复杂度极低,适合处理大规模数据。 | 
| 缺点 | 数据规模大时性能极差(例如 n=1e6 时需 1e6 次操作)。 | 需显式处理空数组和越界问题,仅适用于有序数组。 | 
