持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
题目描述
原题链接 :
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 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 <= 10^4
- -10^4 <= nums[i] <= 10^4
- nums 为 无重复元素 的 升序 排列数组
- -10^4 <= target <= 10^4
思路分析
三部曲不多说;
这道题可以采用普通的双指针对撞,但是复杂度稍微高点。可以用二分查找。
首位双指针,求他们的mid位置,比较mid位置的值,然后移动首位指针之一到mid上。
需要注意的是循环结束的条件,p1<p2-1;以免陷入p1一直等于mid的循环中;
最后判断p1、p2位置和目标值的大小关系,以确定目标值的位置。
AC 代码
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
if(!nums){
return 0
}
var len = nums.length;
var p1 = 0;
var p2 = len -1;
while(p1<p2-1){
var mid = Math.floor(p1+(p2-p1)/2)
if(nums[mid]===target){
return mid
}else if(nums[mid]>target){
p2=mid
}else{
p1=mid
}
}
if(nums[p1]>=target){
return p1
}else if(nums[p2]<target){
return p2+1
}else{
return p2
}
};
总结
注意容易出错的 3 个地方。
循环退出条件是 low <= high,而不是 low < high;
mid 的取值,可以是 mid = (low + high) / 2,但是如果 low 和 high 比较大的话,low + high 可能会溢出,所以这里写为 mid = low + ((high - low) >> 1);
low 和 high 的更新分别为 low = mid + 1、high = mid - 1。