二分查找没有变形

二分查找没有变形

  • 经典的二分查找相信大家都已烂熟于心,但是经典的二分查找只给出了true或false的回答,也就是是否存在,存在返回true,不存在则返回false。但是,基于经典的二分查找却会有很多的变式,每一种变式可能都会有相应的代码解决方案,本文之所以命名为"二分查找没有变形",是因为我找到了一个统一的思路,无论哪种变形都能根据此思路写出相应的代码。

本文默认约束

  1. 是从数组中查找某一个特定的元素(不一定是等于该目标元素,可能是大于等于目标元素,或者小于等于目标元素),并且数组从小到大排序;
  2. 左右边界分别为start=0,end=len(data)-1,也就是说查找的区间是[start,end],左右都是闭区间;
  3. 为了代码简洁,本文使用的是python语言,但是我并没有使用python语言特有的函数,只要有其他任何语言基础,都能够很方便转成自己需要的语言;
  4. 在求mid时,可能会有溢出,或者考虑到效率问题,本文重点在于统一二分查找的思路,对于这种细枝末节的优化问题不予讨论。
  5. 上述所有约束都是为了描述方便,我相信只要你看懂了我的思路,可以很方便地举一反三,比如对于约束1,数组默认从小到大排序,那么只要你看懂了我的思路,数组如果是从大到小排序也是很快能够掌握的。

思路分析

  • 以一个具体的例子来说明我的思路
    在一个从小到大排序的数组data中,找到第一个大于等于key的元素的下标,如果不存在则返回-1.题目来了,那么如何写出相应的代码呢。
  • 步骤详解一(while 循环部分,注意循环的条件是start<=end):
    1. 先写出不满足条件的情况。题目中说"找到第一个大于等于key"的,先不管第一个还是最后一个,重点在于"大于等于key",所以,第一个判断条件就是if data[mid]<key,此时的决策因该是start=mid+1。注意这里不满足的条件只有一个,如果要求"找到第一个等于key的元素",那么不满足条件就有两种情况,所以要写两个if判断。
    2. 能够走到第二步说明已经满足了条件,也就是说当前data[mid]>=key,那么此时应该如何决策呢,这就是本文的重点,此时的决策依旧比较困难,还应该做一步判断,if mid==0 or data[mid-1]<key,这步判断是什么意思呢,就是解决题目中所要求的"第一个大于等于key"的问题,如果当前mid==0或者data[mid-1]<key都说明mid是data中"第一个大于等于key"的元素的下标,此时的决策是return mid
    3. 能够走到这里说明第二步中if mid==0 or data[mid-1]<key不满足,也就是说mid>0 and data[mid-1]>=key,那么说明什么问题?说明在mid之前,还有大于等于key的元素,那么此时的决策应该是end=mid-1
  • 步骤详解二(跳出while循环部分)
    能够走到这里一定是start>end,也就是说数组中没有找到这样的元素,直接返回-1。
  • 完整的代码如下
def binary_search(data, start, end, key):
    while start <= end:
        mid = (start+end)//2
        if data[mid] < key:
            start = mid + 1
        elif mid == 0 or data[mid-1] < key:
            return mid
        else:
            end=mid-1
    return -1
  • 有了这个基础,那么写其他的变形就易如反掌了,如果还不太清楚,欢迎讨论。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值