代码随想录
https://programmercarl.com/0035.搜索插入位置.html
题目
35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 0(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为无重复元素的升序排列数组
- -104<=target<=104
解题
暴力解法
暴力解法真是简单易懂啊。
时间复杂度:O(n),空间复杂度:O(1)。
var searchInsert = function (nums, target) {
for (let i = 0; i < nums.length; i++) {
if (target <= nums[i]) {
return i;
}
}
return nums.length;
};
二分查找
既然是无重复的有序数组,就不得不提到降低时间复杂度的神器二分查找了(有重复的话用二分查找可能导致二分查找找到的索引不唯一)。
时间复杂度:O(log n),空间复杂度:O(1)
先自己写了一遍,二分查找比较熟悉了,但我弄不清数组里找不到时应返回多少,也没考虑清楚所有情况。测试了很多遍才勉强写出来。
var searchInsert = function(nums, target) {
// 先二分查找,坚持左闭右闭
let left = 0, right = nums.length - 1, mid;
while(left <= right) {
mid = left + ((right - left) >> 1);
if (target > nums[mid]) {
left = mid + 1;
} else if(target < nums[mid]) {
right = mid - 1;
} else {
// 若数组中存在target,则会在这里返回它的索引
return mid;
}
}
// 当找遍了数组都没找到时,
// 一种情况是target应插入到mid的左边(即mid)
// 另一种情况是target应插入到mid的右边(即mid+1)
if (target < nums[mid]) {
return mid;
} else if (target > nums[mid]) {
return mid + 1;
}
};
看了代码随想录的范例以后发现我搞复杂了。以下是修改版:
var searchInsert = function(nums, target) {
// 先二分查找,坚持左闭右闭
let left = 0, right = nums.length - 1;
while(left <= right) {
... // 二分查找部份
}
// right=left-1,导致程序退出二分查找,说明数组中找不到target,有三种可能:
// 1. target较小,应插入队头,返回索引为0。此时left = 0,right = -1
// 2. target较大,应跟在队尾,返回索引为nums.length。此时left = nums.length,right = nums.length-1
// 3. target中等大小,应插入nums[right]与nums[left]之间,返回索引为left
return left;
};