python中的bisect模块与二分查找详情
作者:独影月下酌酒 发布时间:2021-07-23 05:17:56
1.bisect模块概述
bisect是python的内置模块, 用于有序序列的插入和查找。 插入的数据不会影响列表的排序, 但是原有列表需要是有序的, 并且不能是倒序.
Bisect模块提供的函数有:
bisect.bisect_left(a,x, lo=0, hi=len(a))
bisect.bisect_right(a,x, lo=0, hi=len(a))
bisect.bisect(a, x,lo=0, hi=len(a))
bisect.insort_left(a,x, lo=0, hi=len(a))
bisect.insort_right(a,x, lo=0, hi=len(a))
bisect.insort(a, x,lo=0, hi=len(a))
2.bisect模块的函数详解
2.1 bisect.bisect*()方法
bisect.bisect_left(a,x,lo=0,hi=len(a),*,key=None)
在有序数组a中[lo,hi]区间内查找x插入的位置,返回的是索引值。如果a中有跟x相同的元素,则x插入的位置是左边,key指定了一个单参数的方法,该方法的返回值作为与k比较的基准。
值得注意的是,key参数是3.10版本以后才添加的功能
bisect.bisect_right(a,x,lo=0,hi=len(a),*,key=None),在有序数组a中[lo,hi]区间内查找x插入的位置,返回索引值。如果a中有跟x相同的元素,则x插入的位置是右边。
bisect.bisect(a,x,lo=0,hi=len(a),*,key=None),同bisect_right
# bisect_left Vs. bisect (bisect_right)
import bisect
nums = [1, 2, 2, 4]
i, j = bisect.bisect_left(nums, 2), bisect.bisect(nums, 2)
print(i) # 输出1
print(j) # 输出3
可见,针对上面给出的数组,想要插入2,使用bisect_left返回的索引值是1,使用bisect(bisect_right)返回的索引值是3。如果指定了lo和hi的话,那么返回的就是在这个范围内的索引。如下面的例子所示。
# 指定lo和hi
import bisect
nums = [1, 2, 2, 2, 2, 4]
i = bisect.bisect_left(nums, 2, 3)
print(i) # 输出为3
如果不指定lo=3的话,返回的索引应该是1。指定lo=3后,返回的索引为3。
关键字key指定了一个方法,这个方法会接受当前数组中的中间值mid(因为二分查找就是从中间值开始的)作为其参数,然后返回一个值val,val用于跟x比较。
# 指定key值
import bisect
nums = [1, 2, 3, 4, 6, 8]
def divide(mid):
print('mid: ' + str(mid))
return mid // 2
i = bisect.bisect_left(nums, 5, key=divide)
print(i)
上面的例子中定义了一个divide方法。那么bisect_left方法的执行顺序是这样的:
nums中的中间值mid=4, divide(mid)方法返回值为2
5>2,则查找nums的右子数组,即[6,8]
[6,8]的中间值是mid=8, divide(mid)方法返回值为4
5>4,则继续查找右子数组,可是已经没有右子数组了,则返回索引值为6.
2.2 bisect.insort*()方法
bisect.insort_left(a,x,lo=0,hi=len(a),*,key=None),在有序数组a中[lo,hi]区间内查找x插入的位置,返回的是索引值。如果a中有跟x相同的元素,则x插入的位置是最左边,key指定了一个单参数的方法,该方法的返回值作为与k比较的基准。
bisect.insort_right(a,x,lo=0,hi=len(a),*,key=None),在有序数组a中[lo,hi]区间内查找x插入的位置,返回索引值。如果a中有跟x相同的元素,则x插入的位置是最右边。
bisect.insort(a,x,lo=0,hi=len(a),*,key=None),同insort_right。
# bisect.insort_left
import bisect
nums = [1, 2, 3, 4, 6, 8]
bisect.insort_left(nums, 5)
print(nums)
# [1, 2, 3, 4, 5, 6, 8]
值得注意的是,insort方法中的key和bisect方法中的key指定的方法针对的对象是不同的。
# bisect.insort_left with key
import bisect
nums = [1, 2, 3, 4, 6, 8]
def divide(mid):
print('mid: ' + str(mid))
return mid // 2
bisect.insort_left(nums, 5, key=divide)
可见,key指定的方法的参数是针对x的。也就是说insort_left方法的执行顺序是这样的:
mid=x=5,返回的值是2,也就是divide(x)
mid是数组的中间值,即mid=4, divide方法返回的值是2
divide(x)==2,则查找左子数组
中间值为2,mid=2, divide方法返回的值是1
divide(x)>1,则查找右子数组
中间值为3,mid=3, divide方法的返回值是1
divide(x)>1,则查找右子数组
没有右子数组了,则插入位置的索引为3,得到了插入5之后的数组为[1,2,3,5,4,6,8]
3.python中的二分查找
3.1 标准的二分查找
class BinarySearch:
# 标准的二分查找,找不到返回-1
def binsearch(self, nums, target):
lo, hi = 0, len(nums) - 1
while lo <= hi:
mid = lo + (hi - lo) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
hi = mid - 1
else: # nums[mid] < target:
lo = mid + 1
return -1
3.2 查找第一个>=target的元素索引
class BinarySearch:
# 查找第一个>=target的元素索引,找不到返回数组长度
def lowerbound(self, nums, target):
lo, hi = 0, len(nums) - 1
pos = len(nums) # 找不到
while lo < hi:
mid = lo + (hi - lo) // 2
if nums[mid] >= target:
hi = mid
else: # nums[mid] < target:
lo = mid + 1
if nums[lo] >= target: # lo:要找的元素索引
pos = lo
return pos
3.3 查找第一个>target的元素索引
class BinarySearch:
# 查找第一个>target的元素索引,找不到返回数组长度
def upperbound(self, nums, target):
lo, hi = 0, len(nums) - 1
pos = len(nums) # 找不到
while lo < hi:
mid = lo + (hi - lo) // 2
if nums[mid] > target:
hi = mid
else: # nums[mid] <= target:
lo = mid + 1
if nums[lo] > target: # lo:要找的元素索引
pos = lo
return pos
4.二分查找的变形与 bisect 模块的关系
二分查找中的
lowerbound(nums, target)
等价于bisect.bisect_left(a,x, lo=0, hi=len(a))
二分查找中的
upperbound(nums, target)
等价于bisect.bisect_right(a,x, lo=0, hi=len(a))
或者bisect.bisect(a,x, lo=0, hi=len(a))
来源:https://blog.csdn.net/weixin_44852067/article/details/126815828


猜你喜欢
- 一、概述音频时域波形具有以下特征:音调,响度,质量。我们在进行数据增强时,最好只做一些小改动,使得增强数据和源数据存在较小差异即可,切记不能
- hello,大家好,我是Dream。马上就跨年了,为了广大的单身男性成员,我就慈悲一下,把我的存货–表白神器拿出来了,百试百灵(虽然我一次也
- 什么是typescripttypescript 为 javaScript的超集,这意味着它支持所有都JavaScript都语法。它很像Jav
- 前言这篇博文发布后,有朋友问有没有SQL server版本的,现在有了==》传送门一、场景再现在一个erp进销存系统或0A等其他系统中,如果
- 本文记录了PyCharm安装的图文教程,供大家参考,具体内容如下PyCharm的官网 1.在官网下载安装包2.选择Windows系
- 由于不同的项目需要用不同的python版本,于是使用Anaconda来进行版本管理,现记录一下经验:在官网下载并安装好Anaconda以后(
- 自从2005年8月11日阿里巴巴宣布收购雅虎中国的全部资产后,做为阿里巴巴集团的创始人马云心里盘算的事应该是如何把雅虎中虎整合进阿里巴巴这个
- <html><head><meta http-equiv=Content-Type content="
- 这两天准备复习一下java,所以写一个采用dubbo的商场项目练练手,却卡第一个测试上,启动provider服务和Consumer服务,请求
- 网页情况爬取数据包含歌曲排名、歌手、歌曲名、歌曲时长python 代码import requests #请求网页获取网页数据 f
- 之前遇到过MySQL本地可以连接但是远程连不上的问题,没有记录,今天在云上新申请的服务器上又遇到这个问题,记录一下解决过程。1.排除网络或防
- 需要先安装openpyxl库通过pip命令安装: pip install openpyxl源码如下:#!/usr/bin/python3#-
- 准备在以后制作的网站中尝试一些变化,比如:先提交内容,后提示注册/登陆。感觉这样可以绑架更多用户……不想注册再发言?那就先让你上钩发言,然后
- 前言:最近工作上遇到个问题,项目开发过程中,开发代码可以通过svn来版本控制,但数据库又该如何来管理呢?多个人接触数据库,当对表、字段或数据
- 业务场景:关联不同数据库中的表的查询比如说,要关联的表是:机器A上的数据库A中的表A && 机器B上的数据库B中的表B。这种
- 需求开发过程中开发者经常面对的一个需求就是:一个项目可能会在不同的环境下运行,本地开发环境、测试环境、灰度环境、生产环境。每个环境的参数和配
- 本文实例为大家分享了python多进程共享变量的相关代码,供大家参考,具体内容如下from multiprocessing import P
- pandas中遍历dataframe的每一个元素假如有一个需求场景需要遍历一个csv或excel中的每一个元素,判断这个元素是否含有某个关键
- 引言webpack插件CommonsChunkPlugin的主要作用是抽取webpack项目入口chunk的公共部分,具体的用法就不做过多介
- 代码如下# 爬取网易音乐import requestsfrom bs4 import BeautifulSoupimport urllib.