开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第38天,点击查看活动详情
题目描述
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
来源:力扣(LeetCode)
- 示例 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
思路分析
根据题意可知,题目给出一个排序数组nums和一个目标值target。需要在数组中找到目标值,并且返回索引。如果目标值没有在数组里面,就返回它将会被按顺序插入的位置。并且需要使用时间复杂度为 O(log n) 的算法。
这里有许多可能性,如果数组nums中的元素都比target小,那么target就是需要插入到数组的最后面;反之,如果数组nums中的元素都比target大,那么target就需要插入到数组的最前面。
如果数组中间的数值等于target,那么就直接返回数组中间的下标。
如果数组中的数值大于target,就需要往左边的元素区间[left, mid]之间取中间值做比较;如果刚好这样取到的中间值等于target,那就可以直接将此时的中间值的下标返回出去,如果不相等,就继续上面的操作继续做左边的中间值做比较。如果取到左边的值比target值小,右边的值比target大,两个值又相邻,那么就将值插在中间
AC代码
function solution(nums, target) {
let left = 0;
let right = nums.length-1;
let mid = Math.floor(nums.length/2);
if(nums[right] < target) {
return nums.length;
}
if(nums[left] > target) {
return 0;
}
while(true) {
if(nums[mid] === target) {
return mid;
}else if(nums[mid] < target) {
left = mid;
mid = left + Math.floor((right- left)/2)
}else{
right = mid;
mid = left + Math.floor((right-left)/2)
}
if(nums[left] === target) {
return left;
}
if(nums[right] === target) {
return right;
}
if(nums[left] != target && nums[right] != target && right-left == 1) {
return left+1;
}
}
}
let nums = [1,3,5,6], target = 4;
solution(nums, target);