【LeetCode】35. 搜索插入位置
1 题目描述
35. 搜索插入位置要求根据给定一个排序数组 nums
和一个目标值 target
,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,则返回它将会被按顺序插入的位置。要求使用的时间复杂度为 O(log n)。
2 解题思路
由于题目要求使用 O(log n) 的时间复杂度,我们自然想到使用二分查找法来解决这个问题。二分查找的基本思想是在有序数组中查找一个值,每次比较中间元素,根据比较结果缩小查找范围直到找到目标或者确定目标不在数组中。
对于本题,我们需要做以下调整以处理目标值不存在的情况:
- 初始化:定义两个指针
left
和right
分别表示搜索区间的起始和结束位置。 - 循环条件:当
left <= right
时,搜索区间有效,继续执行循环。 - 中间位置:计算中间位置
middle = left + (right - left) / 2
,这样可以避免整数溢出。 - 比较并更新:
- 如果
nums[middle] == target
,则找到目标值,返回middle
。 - 如果
nums[middle] > target
,则目标值在左侧子数组中,更新right = middle - 1
。 - 如果
nums[middle] < target
,则目标值在右侧子数组中,更新left = middle + 1
。
- 如果
- 终止条件:如果退出循环,说明没有找到目标值。此时
left
指针指向了应该插入的位置,返回left
。
3 Java 代码实现
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int middle = left + (right - left) / 2;
if (nums[middle] == target) {
return middle; // 直接返回匹配的索引
} else if (nums[middle] < target) {
left = middle + 1; // 缩小左侧范围
} else {
right = middle - 1; // 缩小右侧范围
}
}
return left; // 循环结束后,left 指向目标应该插入的位置
}
}
3.1.1.1 注意事项
- 确保在计算中间位置时使用
left + (right - left) / 2
而不是(left + right) / 2
来避免整数溢出问题。 - 初始设置
right
为nums.length - 1
,这是因为索引从 0 开始,最后一个元素的索引是length - 1
。 - 循环条件是
left <= right
而不是left < right
,这是因为我们需要包含left == right
的情况,这可能是目标值所在的单个元素。 - 退出循环终止时,
left
指向了数组中第一个大于或等于target
的元素的位置,或者是数组末尾的下一个位置(如果所有元素都小于target
),因此直接返回left
即可。