q35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
可以假设数组中无重复元素。
题解:
本题使用二分法,先设定左侧下标left,为0,和右侧下标right,为数组长度减一。根据left和right算出mid,然后判断目标值和数组最中间的值的大小,如果目标值大,则缩短查找区间为[mid+1,right],所以此时让left = mid+1,如果目标值小,则可缩短查找区间为[left,mid-1],此时让right = mid -1,如果目标值和中间值相等,则返回中间值的下标,即mid。查找结束如果没有相等值,则返回 left,该值为插入位置。
具体代码如下:(注意边界条件)
var searchInsert = function(nums, target) {
let left = 0,right = nums.length-1
while(left<=right){
let mid = Math.floor((left+right)/2)
if(nums[mid]==target){
return mid
}else if(nums[mid]<target){
left = mid+1
}else{
right = mid-1
}
}
return left
};
q34. 在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
算法时间复杂度必须是 O(log n) 级别。
如果数组中不存在目标值,返回 [-1, -1]。
题解:
本题的难点主要在于,一个元素可能可以在有序数组中出现多次,使用二分法时要确定此元素的第一个位置和最后一个位置,需要分别查找左右边界值。
如果当前看到的元素恰好等于 target,那么当前元素有可能是 target 出现的第 1 个位置,因为我们要找第 1 个位置,此时我们应该向左边继续查找;
如果当前看到的元素严格大于 target,那么当前元素一定不是要找的 target 出现的第 1 个位置,第 1 个位置肯定出现在 mid 的 左边 ,因此就需要在 [left, mid] 区间里继续查找;
如果当前看到的元素严格小于 target,那么当前元素一定不是要找的 target 出现的第 1 个位置,第 1个位置肯定出现在 mid 的 右边 ,因此就需要在 [mid + 1, right] 区间里继续查找。
使用JavaScript解题如下:
var searchRange = function(nums, target) {
let left_bound = function () {
let left = 0,right = nums.length-1
while(left<=right){
let mid = Math.floor((left+right)/2)
if(nums[mid] === target){
right = mid -1
}else if(nums[mid] < target){
left = mid +1
}else{
right = mid-1
}
if (left !== nums.length && nums[left] === target){
return left
}
}
return -1
}
let right_bound = function () {
let left = 0,right = nums.length-1
while(left<=right){
let mid = Math.floor((left+right)/2)
if(nums[mid] === target){
left = mid +1
}else if(nums[mid] < target){
left = mid +1
}else{
right = mid-1
}
if (right !== -1 && nums[right] === target){
return right
}
}
return -1
}
let end = right_bound()
let start = left_bound()
return [start,end]
};