难度:简单
题意抽象化:在一个有序数组里查找目标值是否存在
首先想到的解题思路:for循环数组,一一去比较目标值是否在数组里存在:
for(let i =0 ;i<nums.length;i++){
if(target === nums[i]){
return [i]
}....//省略
其实这种解题思路是非常低效的,我们要学会抓取题目关键字:
有序整型数组,由于数组是有序的,我们可以用二分查找的方法来解决。
//正确高效解题思路
var search = function(nums, target) {
let begin = 0;
let end = nums.length-1;
let mid;
while(begin<=end){
//方法1
mid = (begin+end) >> 1;
//方法2
//mid = Math.floor((begin+end)/2)
if(nums[mid] === target) return mid;
//三元运算符
let isSmall = nums[mid]<target;
begin = isSmall? mid+1 : begin;
end = isSmall? end : mid-1;
}
return -1;
};
易错:
中间值的取值:mid = (begin+end)/2
忽略了以下情况:若begin = 4 end = 5 mid=9/2 = 4.5
找不到下标为4.5的值,那么正确的是要向下取整
方法1:js 右移
16>>1结果为8:16*(1/2^1)
8>>1结果为4:8*(1/2^1)
4>>2结果为1:4*(1/2^2)
结果为express*(1/2^n)
同理右移:>>
结果为express*2^n
方法2:js Math.floor() 方法
延伸题:搜索插入位置:若目标值没有在有序数组内,按顺序插目标值
我的思路及解法:
var searchInsert = function(nums, target) {
let begin = 0;
let end = nums.length;
let mid;
while (begin<=end){
mid = Math.floor((begin+end)/2)
if(nums[mid] === target) return mid;
let isSmall = nums[mid] < target;
begin = isSmall? mid+1 : begin;
end = isSmall? end : mid-1;
}
if(target < nums[begin] && begin ===0)
return 0
if (target > nums[begin] && begin !=0)
return begin+1
if(target > nums[end])
return end+1
};
延伸点:当目标值不在数组内,如何搜索插值
思路:分以下几种插值位置情况
【头部】:
a.比索引为0的值小 => 插值的索引为0
b.比索引为0的值大 => 插值的索引为begin+1
【中部】
索引值不为0 => 当target<nums[begin];插值索引即为begin 或 当target > nums[begin] ;插值索引为begin+1
【尾部】==>关注’end’
当targer > nums[end] ,插值索引为end+1
优化做法:
var searchInsert = function(nums, target) {
let begin = 0;
let end = nums.length-1;
let ans = nums.length;
while (begin<=end){
const mid = begin + Math.floor((end - begin)/2)
if(target > nums[mid]){
begin = mid + 1;
}else{
ans = mid;
end = mid - 1;
}
}
return ans;
};