算法心得——二分查找

二分查找模板

二分查找常用在有序数组中找到某个元素或插入某个元素,关于二分查找方法的详细介绍和分析可以看力扣上这一篇大神级题解:用「排除法」(减治思想)写二分查找问题、与其它二分查找模板的比较

对每次查找区间的选取不同会有很多种不同的模板,这里只把我最常用的思路模板写一下:

left = 0
right = arr.lenght-1
while(left < right) {
	// 注意这里是向下取整
	mid = Math.floor((left + right)/2)
	if(target > arr[mid]) {
		left = mid+1
	} else {
		right = mid
	}
}
// 这里 return left 是因为循环到最后left代表两种意思
// 1. 数组中有target元素,此时left就是target元素的下标
// 2. 数组中没有target元素,此时left就是本来target元素的位置,即应该插入的位置
return left

要理解返回left的意义,建议做一下力扣的这一题:搜索插入位置

判断数组中是否有target元素

要判断是否有target,首先要在if..else中添加一个target == arr[mid]的判断,找到了就直接return mid,但是这里要注意一个特殊情况,比如在数组[5,7,8,10]中找到10,最后你会发现当left=mid+1left 会等于 right直接跳出while循环,没办法再判断是否等于target,为了解决这个bug,在循环完成后再加个判断。

// 没有找到对应的题目,就写个模版吧
left = 0
right = arr.lenght-1
while(left < right) {
	// 注意这里是向下取整
	mid = Math.floor((left + right)/2)
	if(target > arr[mid]) {
		left = mid+1
	} else if(target == arr[mid]) {
		return mid
	} else {
		right = mid
	}
}
// 这里再加个判断,注意啦,是使用left判断
if(arr[left] == target) return left
// 没有找到返回 -1
return -1

其实,还有一个更简单的解决办法,不需要再添加判断条件,就是在最开始赋值的时候,直接让right = arr.lenght,多给right加一个长度,就能避免现有问题,且永远也取不到arr[arr.length],不会有undefined情况。

统计数字在排序数组中出现的次数

var search = function(nums, target) {
    let left = 0;
    // 避免出现无法判断最后一次情况
    let right = nums.length;
    let count = 0;
    while(left < right) {
        mid = Math.floor((right + left)/2);
        if(nums[mid] > target) {
            right = mid;
        } else if(nums[mid] < target){
            left = mid+1;
        } else {
            // 找到目标元素,判断有几个
            let a = mid;
            let b = mid-1;
            // 往左边找
            while(nums[mid] == nums[a]) {
                a++;
                count++;
            }
            // 往右边找
            while(nums[mid] == nums[b]) {
                b--;
                count++;
            }
            return count;
        }
        
    }
    return count;
};

在部分排序数组中的应用

有些数组只是部分有序,也能使用二分查找寻找元素位置,比如搜索旋转排序数组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值