题目描述:
题号:35
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n)
的算法。
解题思路:
思路一:二分法
题目要求时间复杂度为 O(log n), 而暴力法时间复杂度为 O( n )。显然题目想让我们使用二分查找来解决这个问题。
直接套用二分查找即可,即不断的二分查找并接近第一个大于等于目标的元素。
代码中最后 return left 的原因:left
恰好指向了应该插入目标值的位置 —— 每次更新 left
和 right
时都是基于 mid
与 target
的比较结果,因此当循环结束时,left
会指向第一个大于目标值的位置(如果存在的话),或者如果数组中所有值都小于或等于目标值,left
就会等于数组的长度(因为最后一次迭代中 mid
会指向数组的最后一个元素,而由于它小于或等于目标值,left
会被更新为 mid + 1
,即数组长度)
时间复杂度:O(N)
空间复杂度:O(1)
C++
// C++
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
if(nums.size() == 0) {
return 0;
}
int n = nums.size();
int left = 0, right = n - 1;
while(left <= right) {
int mid = (right - left)/2 +left;
if(nums[mid] < target) {
// 目标在 mid 右侧
left = mid + 1;
} else if(nums[mid] > target) {
// 目标在 mid 左侧
right = mid - 1;
} else {
// 目标存在,返回索引值
return mid;
}
}
return left;
}
};
go
// go
func searchInsert(nums []int, target int) int {
if len(nums) == 0 {
return 0
}
n := len(nums)
left, right := 0, n - 1
for left <= right {
mid := (right - left)/2 + left
if nums[mid] < target {
// 目标在 mid 右侧
left = mid + 1
} else if nums[mid] > target {
// 目标在 mid 左侧
right = mid - 1
} else {
// 目标存在,返回索引值
return mid
}
}
return left
}