使用bisect库实现二分查找
手动实现
假如有一个有序表nums,怎么样在nums里找到某个值的位置呢?没错,就是nums.index(k),哈哈哈哈哈哈哈……
假如nums很长很长,那就要祭出二分查找了
def binary_search(nums: List[int], k: int) -> int:
if not nums:
raise ValueError('list is empty')
left, right = 0, len(nums)-1
while left <= right:
mid = (right + left) // 2
if k < nums[mid]:
right = mid - 1
elif k > nums[mid]:
left = mid + 1
else: # if k == nums[mid]:
return mid
raise ValueError(f'{k} is not in list')
计算mid的公式为
(right + left) / 2,动态语言随便写,但是在静态语言中建议写成left + (right - left) / 2,这样可以防止right和left都很大时,(right + left)溢出。
使用bisect
二分查找可以给查找加速,但是每次写这么一段代码也够心烦。其实Python有这么一个库:bisect 这个库实现了二分查找和二分插入。
bisect的方法数量不多,参考官方文档给出的说明:
bisect.bisect_left(a, x, lo=0, hi=len(a))
在 a 中找到 x 合适的插入点以维持有序。参数 lo 和 hi 可以被用于确定需要考虑的子集;默认情况下整个列表都会被使用。如果 x 已经在 a 里存在,那么插入点会在已存在元素之前(也就是左边)。如果 a 是列表(list)的话,返回值是可以被放在 list.insert() 的第一个参数的。
返回的插入点 i 可以将数组 a 分成两部分。左侧是 all(val < x for val in a[lo:i]) ,右侧是 all(val >= x for val in a[i:hi]) 。bisect.bisect_right(a, x, lo=0, hi=len(a))
bisect.bisect(a, x, lo=0, hi=len(a))
类似于 bisect_left(),但是返回的插入点是 a 中已存在元素 x 的右侧。
返回的插入点 i 可以将数组 a 分成两部分。左侧是 all(val <= x for val in a[lo:i]),右侧是 all(val > x for val in a[i:hi]) for the right side。bisect.insort_left(a, x, lo=0, hi=len(a))
将 x 插入到一个有序序列 a 里,并维持其有序。如果 a 有序的话,这相当于 a.insert(bisect.bisect_left(a, x, lo, hi), x)。要注意搜索是 O(log n) 的,插入却是 O(n) 的。bisect.insort_right(a, x, lo=0, hi=len(a))
bisect.insort(a, x, lo=0, hi=len(a))
类似于 insort_left(),但是把 x 插入到 a 中已存在元素 x 的右侧。
参见: SortedCollection recipe 使用 bisect 构造了一个功能完整的集合类,提供了直接的搜索方法和对用于搜索的 key 方法的支持。所有用于搜索的键都是预先计算的,以避免在搜索时对 key 方法的不必要调用。
搜索有序列表
上面的 bisect() 函数对于找到插入点是有用的,但在一般的搜索任务中可能会有点尴尬。下面 5 个函数展示了如何将其转变成有序列表中的标准查找函数
def index(a, x):
'Locate the leftmost value exactly equal to x'
i = bisect_left(a, x)
if i != len(a) and a[i] == x:
return i
raise ValueError
def find_lt(a, x):
'Find rightmost value less than x'
i = bisect_left(a, x)
if i:
return a[i-1]
raise ValueError
def find_le(a, x):
'Find rightmost value less than or equal to x'
i = bisect_right(a, x)
if i:
return a[i-1]
raise ValueError
def find_gt(a, x):
'Find leftmost value greater than x'
i = bisect_right(a, x)
if i != len(a):
return a[i]
raise ValueError
def find_ge(a, x):
'Find leftmost item greater than or equal to x'
i = bisect_left(a, x)
if i != len(a):
return a[i]
raise ValueError
以上内容摘自官方文档,官方文档有了中文版以后可太友好了。然后照猫画虎实现一个新的binary_search函数,参考上面的index()
def binary_search(nums: List[int], k: int) -> int:
if not nums:
raise ValueError('list is empty')
i = bisect.bisect_left(nums, k)
if i != len(nums) and nums[i] == k:
return i
raise ValueError(f'{k} is not in list')
是不是比手动实现的二分查找简洁多了?
使用bisect库实现二分查找的更多相关文章
- python bisect 排序模块 二分查找与 bisect 模块
python 3.6.5 import bisect bisect_list=dir(bisect)print(bisect_list)bisect_list = ['__builtins__', ' ...
- 二分查找与 bisect 模块
Python 的列表(list)内部实现是一个数组,也就是一个线性表.在列表中查找元素可以使用 list.index() 方法,其时间复杂度为O(n).对于大数据量,则可以用二分查找进行优化.二分查找 ...
- python二分查找模块bisect
bisect模块用于二分查找,非常方便. Bisect模块提供的函数有: 1.查找 bisect.bisect_left(a,x, lo=0, hi=len(a)) : 查找在有序列表a中插入x的in ...
- bisect 二分查找
先说明的是,使用这个模块的函数前先确保操作的列表是已排序的. 先看看 insort 函数: 其插入的结果是不会影响原有的排序. 再看看 bisect 函数: 其目的在于查找该数值将会插入的位置并返 ...
- C++算法库学习__std::sort__对 vector进行排序_排序后就可以进行使用std::lower_bound进行二分查找(查找第一个大于等于指定值的迭代器的位置)__std::unique
std::sort 对vector成员进行排序; std::sort(v.begin(),v.end(),compare); std::lower_bound 在排序的vector中进行 ...
- 分治算法(二分查找)、STL函数库的应用第五弹——二分函数
分治算法:二分查找!昨天刚说不写算法了,但是突然想起来没写过分治算法的博客,所以强迫症的我…… STL函数库第五弹——二分函数lower_bound().upper_bound().binary_se ...
- C++STL标准库学习笔记(二)二分查找
二.STL中的二分查找算法 1.binary_search 2.lower_bound 3.upper_bound 记得#include<algorithm>! 前言: 在这个笔记中,我把 ...
- 【转】STL之二分查找 (Binary search in STL)
Section I正确区分不同的查找算法count,find,binary_search,lower_bound,upper_bound,equal_range 本文是对Effective STL第4 ...
- 三分钟教你学Git(十三) - 二分查找
比方说你收到了错误报告,然后你知道前几天明明是好的.可是这几天有好多新的commit被部署了.那么我们怎么迅速的找到第一个引入Bug的commit呢? 我们能够使用git bisect,git利用二分 ...
随机推荐
- 原生javascript实现选项卡(基础版)
一.实现原理 1.主要运用“排他思想”,在设置当前元素前,先把相应元素恢复到默认状态 2.给相应元素添加下标的应用 二.代码展示 <!DOCTYPE html> <html> ...
- Flutter全面屏适配
笔者在这篇文章ReactNative全面屏(Android)适配问题提及了现在的全面屏问题,不仅是Android平台,IOS平台也是,给我的感觉就是手机越来越长了. 现在的手机长宽比早就不是之前的16 ...
- 第一个javaWeb项目-注册界面
基本功能: 实现信息录入到数据库和信息规范检查 题目要求: 项目目录: 网页界面: 程序源码: package Dao; import java.sql.Connection; import java ...
- 2017-10-28 noip模拟赛by WISCO 信息组
第一次做模拟赛,自我感觉良好(大概是这套题比较简单) T1 名称为“数据结构”,这也太坑了点……233 要维护一个数列(初始为零),支持区间加与查询. 查询的是一个区间中有多少数满足min<=( ...
- NHibernate 初识(0)
参考资料: http://nhibernate.info/
- NOI2.4 2011
描述 已知长度最大为200位的正整数n,请求出2011^n的后四位. 输入 第一行为一个正整数k,代表有k组数据,k<=200接下来的k行, 每行都有一个正整数n,n的位数<=200 输出 ...
- Java容器解析系列(14) IdentityHashMap详解
IdentityHashMap,使用什么的跟HashMap相同,主要不同点在于: 数据结构:使用一个数组table来存储 key:value,table[2k] 为key, table[2k + 1] ...
- livego+obs+flv.js 搭建视频直播
一.流程 主播通过 obs软件通过直播 ->推流到->直播服务器 客户通过浏览器 访问站点->flv.js拉取直播服务器视频流并播放 二.环境 centos7 直播服务器 https ...
- CSS-17-页面布局
页面布局: 静态布局: 静态布局:元素不变的布局. 布局特点:缩小后内容被遮挡,拖动滚动条显示布局 设计方法: PC:居中布局,所有样式使用绝对宽度和高度 移动设备:另外建立移动网站,以m.域名为域名 ...
- Python经典算法-快速幂
快速幂 问题描述: 计算a ** n % b 其中a.b和n都是32位的非负整数 即求a的n次方对b的余数 问题示例: 例如:2**31%3=2 --- 代码实现如下 class Solution: ...