【算法天天练】二分查找(折半查找)+动态搜索插值

难度:简单
在这里插入图片描述
题意抽象化:在一个有序数组里查找目标值是否存在
首先想到的解题思路: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;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值