bisect_left,bisect_right,bisect的用法,区别以及源码分析

简介: bisect_left,bisect_right,bisect的用法,区别和源码分析

bisect_left(args, *kwargs)

向一个数组插入一个数字,返回应该插入的位置。
如果这个数字不存在于这个数组中,则返回第一个比这个数大的数的索引
如果这个数字存在,则返回数组中这个数的位置的最小值(即最左边那个索引)

案例1:这个数在数组中不存在

arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]

# 在已排序的列表中查找元素 6 的插入位置
index = bisect_left(arr, 5.5)

print(f"Insert 6 at index {index} to maintain sorted order.")

执行结果:

Insert 6 at index 4 to maintain sorted order.

我们找到了第一个大于5.5的数字6的位置,输出4

案例2:这个数在数组中存在

我们修改一下代码,寻找6的位置

from bisect import bisect_left, bisect, bisect_right

arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]

# 在已排序的列表中查找元素 6 的插入位置
index = bisect_left(arr, 6)

print(f"Insert 6 at index {index} to maintain sorted order.")

执行结果:

Insert 6 at index 4 to maintain sorted order.

我们发现还是4

bisect_right(args, *kwargs)

向一个数组插入一个数字,返回应该插入的位置。
作用:返回第一个比这个数大的数的索引

案例1:这个数在数组中不存在

from bisect import bisect_left, bisect, bisect_right

arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]

# 在已排序的列表中查找元素 6 的插入位置

index = bisect_right(arr, 6.5)

print(f"Insert 6 at index {index} to maintain sorted order.")

执行结果:

Insert 6 at index 6 to maintain sorted order.

数字7的位置被输出

案例2:这个数在数组中存在

from bisect import bisect_left, bisect, bisect_right

arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]

# 在已排序的列表中查找元素 6 的插入位置

index = bisect_right(arr, 6)

print(f"Insert 6 at index {index} to maintain sorted order.")

执行结果:

Insert 6 at index 6 to maintain sorted order.

数字7的位置被输出

对比bisect_left 和 bisect_right

相同点:
当第二个参数数字x不在第一个参数数组arr中时候,二者都会返回arr中第一个比x大的数的位置

不同点:
当arr中存在x,bisect_left会返回arr中x的最小索引,而bisect_right会返回第一个比x大的数的位置

bisect()

alt

完整代码

from bisect import bisect_left, bisect, bisect_right

arr = [1, 3, 3, 5, 6, 6, 7, 9, 11]

# 在已排序的列表中查找元素 6 的插入位置

index = bisect_right(arr, 6)

print(f"Insert 6 at index {index} to maintain sorted order.")

index = bisect(arr, 6)

print(f"Insert 6 at index {index} to maintain sorted order.")


index = bisect_left(arr, 6)

print(f"Insert 6 at index {index} to maintain sorted order.")

结果:

Insert 6 at index 6 to maintain sorted order.
Insert 6 at index 6 to maintain sorted order.
Insert 6 at index 4 to maintain sorted order.

源码分析

我们先来看 bisect_right 的源码

def bisect_right(a, x, lo=0, hi=None):
    """Return the index where to insert item x in list a, assuming a is sorted.

    The return value i is such that all e in a[:i] have e <= x, and all e in
    a[i:] have e > x.  So if x already appears in the list, a.insert(x) will
    insert just after the rightmost x already there.

    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        # Use __lt__ to match the logic in list.sort() and in heapq
        if x < a[mid]: hi = mid
        else: lo = mid+1
    return lo

bisect_left 的源码

def bisect_left(a, x, lo=0, hi=None):
    """Return the index where to insert item x in list a, assuming a is sorted.

    The return value i is such that all e in a[:i] have e < x, and all e in
    a[i:] have e >= x.  So if x already appears in the list, a.insert(x) will
    insert just before the leftmost x already there.

    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        # Use __lt__ to match the logic in list.sort() and in heapq
        if a[mid] < x: lo = mid+1
        else: hi = mid
    return lo

我们观察到这两种实现方式主要在于下面两行:
bisect_right:

        if x < a[mid]: hi = mid
        else: lo = mid+1

bisect_left:

        if a[mid] < x: lo = mid+1
        else: hi = mid

我们观察到,两段源码都会返回lo,即左边界,所以我们关注一下这两行代码对于左边界的影响:
在bisect_right中,只有当 x=a[mid] or x>a[mid]时,lo才会更新为mid+1,所以最终的lo只可能是第一个大于x的索引
在bisect_left中,当 a[mid] < x时,lo会更新为mid+1,此时我们想要的索引位置必然在mid右侧,所以lo可以为相同的x的第一次出现的位置;同时我们注意到当 a[mid] >= x时,hi=mid,说明当lo取到了相同的数的最左侧时,hi右端点其实会向左平移的,所以lo既可以是数组中第一个大于x的数的索引,也可以是相同的x的最左侧第一个x的索引

目录
相关文章
|
11月前
|
容器
vllm+vllm-ascend本地部署QwQ-32B
本指南介绍如何下载、安装和启动基于Ascend的vLLM模型。首先,可通过华为镜像或Hugging Face下载预训练模型;其次,安装vllm-ascend,支持通过基础镜像(如`quay.io/ascend/vllm-ascend:v0.7.3-dev`)或源码编译方式完成;最后,使用OpenAI兼容接口启动模型,例如运行`vllm serve`命令,设置模型路径、并行规模等参数。适用于大模型推理场景,需注意显存需求(如QwQ-32B需70G以上)。
4278 17
|
11月前
|
数据采集 人工智能 监控
40.8K star!让AI帮你读懂整个互联网:Crawl4AI开源爬虫工具深度解析
Crawl4AI 是2025年GitHub上备受瞩目的开源网络爬虫工具,专为AI时代设计。它不仅能抓取网页内容,还能理解页面语义结构,生成适配大语言模型的训练数据格式。上线半年获4万+星标,应用于1200+AI项目。其功能亮点包括智能内容提取引擎、AI就绪数据管道和企业级特性,支持动态页面处理、多语言识别及分布式部署。技术架构基于Python 3.10与Scrapy框架,性能卓越,适用于AI训练数据采集、行业情报监控等场景。相比Scrapy、BeautifulSoup等传统工具,Crawl4AI在动态页面支持、PDF解析和语义分块方面更具优势
3801 0
40.8K star!让AI帮你读懂整个互联网:Crawl4AI开源爬虫工具深度解析
|
机器学习/深度学习 搜索推荐 算法
深度学习推荐模型-DIN
Deep Interest Network(DIN)是盖坤大神领导的阿里妈妈的精准定向检索及基础算法团队,在2017年6月提出的。 它针对电子商务领域(e-commerce industry)的CTR预估,重点在于充分利用/挖掘用户历史行为数据中的信息。
1456 1
深度学习推荐模型-DIN
|
机器学习/深度学习 人工智能 数据安全/隐私保护
2025年NVIDIA RTX 4090服务器租赁价格与选型详解
随着AI训练、深度学习与图形渲染需求激增,NVIDIA RTX 4090显卡成为算力租赁市场的热门选择。本文从价格体系、配置适配、成本优化三方面解析4090服务器租赁策略,涵盖短租长租价格差异、主流平台对比、硬件配置建议及成本优化方案,助您精准匹配业务需求。此外,还介绍了阿里云高性能GPU实例作为替代方案,提供稳定性和生态集成优势。
|
机器学习/深度学习
大模型中的Scaling Law是什么?
【2月更文挑战第9天】大模型中的Scaling Law是什么?
18895 3
大模型中的Scaling Law是什么?
|
安全 API 网络架构
Python中哪个框架最适合做API?
本文介绍了Python生态系统中几个流行的API框架,包括Flask、FastAPI、Django Rest Framework(DRF)、Falcon和Tornado。每个框架都有其独特的优势和适用场景。Flask轻量灵活,适合小型项目;FastAPI高性能且自动生成文档,适合需要高吞吐量的API;DRF功能强大,适合复杂应用;Falcon高性能低延迟,适合快速API开发;Tornado异步非阻塞,适合高并发场景。文章通过示例代码和优缺点分析,帮助开发者根据项目需求选择合适的框架。
2844 0
|
机器学习/深度学习 人工智能 监控
一文读懂deepSpeed:深度学习训练的并行化
DeepSpeed 是由微软开发的开源深度学习优化库,旨在提高大规模模型训练的效率和可扩展性。通过创新的并行化策略、内存优化技术(如 ZeRO)及混合精度训练,DeepSpeed 显著提升了训练速度并降低了资源需求。它支持多种并行方法,包括数据并行、模型并行和流水线并行,同时与 PyTorch 等主流框架无缝集成,提供了易用的 API 和丰富的文档支持。DeepSpeed 不仅大幅减少了内存占用,还通过自动混合精度训练提高了计算效率,降低了能耗。其开源特性促进了 AI 行业的整体进步,使得更多研究者和开发者能够利用先进优化技术,推动了 AI 在各个领域的广泛应用。

热门文章

最新文章