一天一个算法之二分查找

直接上代码了,要求数组要是有序的。
说明一下,什么是二分查找呢?就是本来我们一般查找一个东西,一般会从头开始找,或者从后面开始,反正会找一个顺序,乱找的话就比较花时间,而二分查找就是总是从中间开始,每次都从现有查找结果的中间开始,不断缩小与真实值的距离。

def binary_search(list,item):      #一个有序数组
    low=0      #因为是有序数组,所以第一个位置的编号是0
    high=len(list)-1      #low和high用于跟踪要在其中查找的列表部分

    while low<= high:      #只要范围没有缩小到质包含一个元素
        mid=(low+high)//2     #就检查中间的元素,如果不是偶数,会向下圆整
        guess=list[mid]
        if guess==item:   #找到元素了
            return mid
        if guess>item:    #猜的数字大了
            high=mid-1
        else:             #猜的数字小了
            low=mid+1
    return None         #没有指定的元素
my_list=[1,3,5,7,9]
print(binary_search(my_list,3))     #表示3在里面的位置,从0开始,所以返回1
print(binary_search(my_list,-1))  # => None  -1不在列表中,返回None

再做一下leetcode上的二分查找题目巩固下:

  1. 统计有序矩阵中的负数:
    给你一个 m * n 的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。
    请你统计并返回 grid 中 负数 的数目。
  • 首先,是有序数组,满足二分查找的要求,但是是个矩阵,就有点难了,我没有想法,怎么从中间开始呢?好像不需要二分吧?看下别人怎么做的。

看下官方解说:

注意到题目中给了一个性质,即矩阵中的元素无论是按行还是按列,都以非递增顺序排列,可以考虑把这个性质利用起来优化暴力。已知这个性质告诉了我们每一行的数都是有序的,所以我们通过二分查找可以找到每一行中从前往后的第一个负数,那么这个位置之后到这一行的末尾里所有的数必然是负数了,可以直接统计。

在这里插入图片描述

class Solution:
    def countNegatives(self, grid: List[List[int]]) -> int:
        return sum(bisect.bisect_left(g[:: -1], 0) for g in grid)

这个太牛逼了,以头抢地了,啥时候才能十秒写出这样的代码?o(╥﹏╥)o
bisect.bisect_left 该函数用入处理将会插入重复数值的情况,返回将会插入的位置,left表示从左边插入0的位置,这里举例就是,比如[5,4,-1,-2],那么0从左边插入的话,是在哪里插入呢?
应该是[5,4,0,-1,-2],那么0的位置是第三个,返回值是2。
可是他是从最后一个数字开始查找,也就是[-2,-1,4,5],返回值一样是2,但是这样可以知道0之前的一定比0小,所以可以直接sum。终于弄明白了o( ̄▽ ̄)d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值