小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
题目
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 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
示例 4:
输入: nums = [1,3,5,6], target = 0 输出: 0
示例 5:
输入: nums = [1], target = 0 输出: 0
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums
为无重复元素的升序排列数组-104 <= target <= 104
解题思路
- 这个题目本质上是利用二分法查找左边界
代码
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function (nums, target) {
if (nums == null || !nums.length) {
return -1;
}
// 左闭右闭区间
let begin = 0,
end = nums.length-1;
while (begin <= end) {
// 下面这样写是考虑大数情况下避免溢出
let mid = begin + ((end - begin) >> 1);
if (nums[mid] > target) {
// 在左半区间中查找
end = mid - 1;
} else if (nums[mid] < target) {
// 在右半区间中查找
begin = mid + 1;
} else {
// 正好就是
return mid;
}
}
// 查找的是左边界,所以返回begin
return begin;
};
思路2
拿到此题,首先看到题目要求二分查找,在原来的二分查找思路上外加一个返回插入的值,至于为什么是return left,是因为当left+1结束时,right执行完此语句也不会对程序产生什么影响
代码
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
let left = 0,right = nums.length - 1;
while (left <= right) {
const mid = Math.floor((right - left)/2) + left;
const mids = nums[mid];
if (mids < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
};
最后
曾梦想仗剑走天涯
看一看世界的繁华
年少的心总有些轻狂
终究不过是个普通人
无怨无悔我走我路