二分查找算法

什么是查找算法

对于一个数组或者是链表,如果想要知道其中是否包含我们需要的target值,可以进行一次线性的查找,每个元素逐个比对来确定是否包含target,这就是一个最简单的查找算法。时间复杂度为O(N)

什么是二分查找算法

假设给定的数组中的元素是一个有序的状态,比如是单调不递减或者是单调不递增的状态,对于这种情况可以使用二分查找来完成。即二分查找需要满足两个条件:

  • 数组存储
  • 元素有序,单调性

二分查找的具体过程

以数组[0,1,2,3,4,5,6]为例。我们需要查找的目标值target是为2,具体的查找过程如下图所示:

  1. 首先要查找的区间是【0,6】,即区间起始位置low=0,区间结束位置high=6。
    在这里插入图片描述
  2. 需要比较区间中间元素和target的大小。中间元素是3,很明显3大于target说明目标元素在target的左半边,瞬间将区间缩小一半。如下图所示。
    在这里插入图片描述
  3. 这时面对的区间是【0,2】,即low=0,high=2,target = 2。同样需要比较区间中间的数和target的大小,区间中间的数是1,比target小。说明target在区间的右半部分。区间同样缩小一半,如下图所示:
    在这里插入图片描述
  4. 这时区间已经变成了【2,2】,low=2,high=2,target= 2同样按照上面的方式计算,找出区间最中间的那个元素,这时中间的元素是2,和目标值target相等,直接返回结果即可。

在这里插入图片描述
上面介绍的是target存在数组中的情况,如果target不存在数组中是什么样的呢?假设target=2.5那么在区间【2,2】之前的查找过程都和上面一样,只有在最后一步时是不一样的。这时同样比较区间【2,2】的中间值和target比较,发现target比该值大,那么就要将low继续往右移动,这时发现 low>high ,说明该元素不在该数组中,可以终止查找了。

二分查找代码

def binary(nums,target):
    low = 0
    high = len(nums) -1
    while low <= high:
        mid = (low + high) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] > target:
            high = mid -1
        else:
            low = mid + 1
    return -1
print(binary([0,1,2,3,4,5,6],2))
print(binary([0,1,2,3,4,5,6],2.5))

一些其他的情况

上面的代码针对的情况是如果target在数组中,那么返回target在数组中的下标;如果target不在数组中则返回-1。对于直接返回-1的这种情况其实是对信息的一种浪费。我们可以返回数组比元素比target小且最接近于target的那个下标。比如数组[0,1,2,3,4,5,6],target = 2.5,这时返回值就应该是2。

返回比该元素大且最接近该元素的下标

def binary(nums,target):
    low = 0
    high = len(nums) -1
    while low <= high:
        mid = (low + high) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] > target:
            high = mid -1
        else:
            low = mid + 1
    return high + 1
print(binary([0,1,2,3,4,5,6],2))
print(binary([0,1,2,3,4,5,6],2.5))

返回比该元素小且最接近于该元素的下标

def binary(nums,target):
    low = 0
    high = len(nums) -1
    while low <= high:
        mid = (low + high) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] > target:
            high = mid -1
        else:
            low = mid + 1
    return low-1
print(binary([0,1,2,3,4,5,6],2))
print(binary([0,1,2,3,4,5,6],2.5))

比如leetcode 354 俄罗斯套娃信封问题中就需要用到返回比该元素小且最接近于该元素的下标 这种二分查找方式,有兴趣的朋友的可以尝试一下。虽然一个基础版本的二分查找代码非常好写,但是对于二分查找的变形的问题还是要深入理解二分查找过程的具体细节,才能在实际中熟练的应用。

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值