「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
题目
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 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
解题思路
方法一:暴力破解
先判断indexOf返回的值是否等于-1,如果不是则返回indexof的值。
判断target是否小于数组最小值nums[0],是则直接返回0;
判断target是否大于数组最大值nums[nums.length - 1],是则返回nums.length;
最后循环数组nums
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
const len = nums.length;
if (nums.indexOf(target) >= 0) return nums.indexOf(target);
if (nums[0] > target) return 0;
if (nums[len - 1] < target) return len;
for (let i = 1; i < nums.length; i++) {
if (nums[i - 1] < target && nums[i] > target) return i;
}
};
由于上面的方法过于繁琐,仔细思考后发现不需要给每一层单独做那么多判断。
可以直接判断target和当前循环的值的大小,如果当前值大于或者等于target的话,则返回当前的index。
否则其他情况则为在数组中没有找到大于或等于目标值的数据,则目标值为最大值,插入数组末尾即可。所以返回数组长度。
优化如下:
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
for (i = 0; i < nums.length; i++) {
if (nums[i] >= target) {
return i;
}
}
return nums.length;
};
当然,虽然上面这种解法能够完美的解决这道问题。但是根据题意我们可以得知,题目想要的是时间复杂度为O(log n)的算法,而我们的这种解题思路时间复杂度为O(n)。
通过我们学习过的算法知识,能够很快的定位到二分查找。👇
方法二:二分查找
/**
* @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;
};
结束语
这里是小葵🌻,只要把心朝着太阳的地方,就会有温暖~
让我们一起来攻克算法难关吧!!