题目
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 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] <= 104nums为 无重复元素 的 升序排列数组-104 <= target <= 104
Java代码
java
class Solution {
public int searchInsert(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
}
核心思路: 标准二分查找。找到了就返回下标,没找到循环结束时 left 就是该插入的位置。
逐行说明:
java
int left = 0, right = nums.length - 1;
标准二分框架,left 从 0 开始,right 从末尾开始。
java
while (left <= right) {
int mid = left + (right - left) / 2;
left + (right - left) / 2 等价于 (left + right) / 2,但避免整数溢出。
java
if (nums[mid] == target) {
return mid; // 找到了,返回下标
} else if (nums[mid] < target) {
left = mid + 1; // 太小,往右找
} else {
right = mid - 1; // 太大,往左找
}
标准二分查找逻辑。
java
return left;
关键 :没找到时,循环结束 left > right,left 就是 target 应该插入的位置。
为什么没找到时 left 就是插入位置?
以 nums = [1,3,5,6], target = 2 为例:
| 轮次 | left | right | mid | numsmid | 操作 |
|---|---|---|---|---|---|
| 1 | 0 | 3 | 1 | 3 | 3>2, right=0 |
| 2 | 0 | 0 | 0 | 1 | 1<2, left=1 |
| 退出 | 1 | 0 | left > right |
nums: [1, 3, 5, 6]
↑
left=1 (插入位置)
2 应该插在 1 和 3 之间,下标 1 ✓
循环结束时 left 停在第一个大于 target 的位置,正好就是插入位置。
三个示例演示:
| target | 过程 | 结果 |
|---|---|---|
| 5 | mid=1→3<5, mid=2→5==5 | 返回 2 ✓ |
| 2 | mid=1→3>2, mid=0→1<2, left=1 | 返回 1 ✓ |
| 7 | mid=1→3<7, mid=2→5<7, mid=3→6<7, left=4 | 返回 4 ✓ |
时间复杂度 O(log n),空间复杂度 O(1)。
python代码
python
class Solution(object):
def searchInsert(self, nums, target):
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return left