Bootstrap

LeetCode35. 搜索插入位置

https://leetcode.cn/problems/search-insert-position/description/

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

示例 1:

输入: nums = [1,3,5,6], target = 5
输出: 2

示例 2:

输入: nums = [1,3,5,6], target = 2
输出: 1

示例 3:

输入: nums = [1,3,5,6], target = 7
输出: 4

提示:

  • 1 <= nums.length <= 104
  • -104 <= nums[i] <= 104
  • nums 为 无重复元素 的 升序 排列数组
  • -104 <= target <= 104

 题解:

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size() - 1;
        while (left <= right) {
            int middle = left + (right - left) / 2;
            if (nums[middle] > target) {
                right = middle - 1;
            } else if (nums[middle] < target) {
                left = middle + 1;
            } else {
                return middle;
            }
        }

        return left;
    }
};

这里展开说一下为什么返回值是left

1. 当目标值小于所有元素时:
nums = [3,5,7], target = 2

过程分析:
第一轮:
- left=0, right=2, middle=1
- nums[1]=5 > target(2)
- right = middle-1 = 0

第二轮:
- left=0, right=0, middle=0
- nums[0]=3 > target(2)
- right = middle-1 = -1

循环结束时:
- left=0, right=-1
- 此时 left 指向的位置(0)正是 target 应该插入的位置

2. 当目标值在中间时:
nums = [3,5,7], target = 6

过程分析:
第一轮:
- left=0, right=2, middle=1
- nums[1]=5 < target(6)
- left = middle+1 = 2

第二轮:
- left=2, right=2, middle=2
- nums[2]=7 > target(6)
- right = middle-1 = 1

循环结束时:
- left=2, right=1
- left 指向的位置(2)正是 target 应该插入的位置

3. 当目标值大于所有元素时:
nums = [3,5,7], target = 8

过程分析:
第一轮:
- left=0, right=2, middle=1
- nums[1]=5 < target(8)
- left = middle+1 = 2

第二轮:
- left=2, right=2, middle=2
- nums[2]=7 < target(8)
- left = middle+1 = 3

循环结束时:
- left=3, right=2
- left 刚好指向数组长度,表示应该插入到数组末尾

为什么总是 left 而不是 right?

  1. 当循环结束时,一定有 left > right
  2. right 总是指向小于 target 的最后一个位置
  3. left 总是指向大于或等于 target 的第一个位置
  4. 因此 left 正好就是 target 应该插入的位置

这样的实现可以正确处理所有情况:

  • 插入位置在最前面:返回0
  • 插入位置在中间:返回正确的插入位置
  • 插入位置在最后面:返回nums.size()
  • 元素已存在:返回该元素的位置

 

;