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?
- 当循环结束时,一定有 left > right
- right 总是指向小于 target 的最后一个位置
- left 总是指向大于或等于 target 的第一个位置
- 因此 left 正好就是 target 应该插入的位置
这样的实现可以正确处理所有情况:
- 插入位置在最前面:返回0
- 插入位置在中间:返回正确的插入位置
- 插入位置在最后面:返回nums.size()
- 元素已存在:返回该元素的位置