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_rightarr = [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_rightarr = [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_rightarr = [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()

我们查看源码发现:
在这里插入图片描述
bisect就是bisect_right

完整代码

from bisect import bisect_left, bisect, bisect_rightarr = [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 ina[i:] have e > x.  So if x already appears in the list, a.insert(x) willinsert just after the rightmost x already there.Optional args lo (default 0) and hi (default len(a)) bound theslice 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 heapqif x < a[mid]: hi = midelse: lo = mid+1return 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 ina[i:] have e >= x.  So if x already appears in the list, a.insert(x) willinsert just before the leftmost x already there.Optional args lo (default 0) and hi (default len(a)) bound theslice 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 heapqif a[mid] < x: lo = mid+1else: hi = midreturn lo

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

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

bisect_left:

        if a[mid] < x: lo = mid+1else: 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的索引

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/286058.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【算法系列篇】递归、搜索和回溯(四)

文章目录 前言什么是决策树1. 全排列1.1 题目要求1.2 做题思路1.3 代码实现 2. 子集2.1 题目要求2.2 做题思路2.3 代码实现 3. 找出所有子集的异或总和再求和3.1 题目要求3.2 做题思路3.3 代码实现 4. 全排列II4.1 题目要求4.2 做题思路4.3 代码实现 前言 前面我们通过几个题目…

Vue中父子Props传值不能修改的原因分析以及解决办法

Vue 官方文档中对于 Prop 的定义&#xff1a; Prop 是你可以在组件上注册的一些自定义属性。当一个值传递给一个 props 属性的时候&#xff0c;它就变成了那个组件实例的一个属性。为了给子组件传递数据&#xff0c;我们需要在该组件上使用 v-bind 指令绑定需要传递的数据。 由…

生物识别应用指纹的算法是什么样的?有什么性能?

方案特点 • 采用金融级安全芯片 ACH512 的指纹模组&#xff0c;指纹和密码安全存储&#xff0c;云端数据安全传输 • 采用高性能指纹专用安全MCU芯片ACM32FP4&#xff0c;支持小点阵图像算法处理 • 支持80*64、88*112、96*96、160*160、192*192等像素传感器 • 已适配传…

亚马逊,速卖通,shein卖家如何准确有效的测评补单

一、合理规划测评时间和数量 卖家需要合理规划测评的时间和数量。如果卖家过于频繁地进行测评&#xff0c;或者在短时间内进行大量的测评&#xff0c;这可能会被视为恶意行为&#xff0c;从而触犯风控机制。因此&#xff0c;卖家需要根据自己的销售情况和市场需求&#xff0c;…

二进制转十六进制字符串的C语言高效率实现(如“10100011“转为字符串“A3“)

对于一串二进制01比特,有时为了显示或者编辑方便高效,我们需要将二进制比特流转换成十六进制,众所周知,二进制转十六进制是每4比特进行转换,例如将以下二进制流: 1010 0011 1100 1101 转换为十六进制应为: A3CD 有时候,还可以每字节中间添加一个空格 A3 CD 下面直接…

Android 应用基准分析

先推荐一个作者的开源项目 最快的Json解析方式 参考 benchmark数据参考 benchmark的例子 可以参考json-benchmark 应用基准分析 是衡量时间维度的框架,是App界的鲁大师跑分,常用于耗时判断,冷启动,热启动,框架对比 预热对比等方面 开局一张图 下面再编 今天要做的是Microbe…

详细教程 - 从零开发 Vue 鸿蒙harmonyOS应用 第七节-—— 鸿蒙应用进程通信深度剖析

一、简介 1.1 进程通信的重要性 不同进程间需要通过通信来协作完成任务良好的IPC机制是构建模块化应用的必要手段 1.2 鸿蒙采用的RPC机制 鸿蒙应用进程通信采用了轻量级RPC,流程如下: 客户端发送请求数据到服务器进程服务器调用函数处理请求,并返回响应客户端获取并处理响应…

Educational Codeforces Round 160 (Rated for Div. 2)(D 动态规划)

关于如何思考DP这件事...这题还是比较好的 思路&#xff1a;考虑为当前共有 i 个数且以为结尾&#xff0c;能够形成的字段的个数。要想求出&#xff0c;只需要知道的前一个数可以是什么&#xff0c;这样就能够进行状态转移了。 首先定义是前方第一个比小的数。 1、首先考虑比…

搭建知识付费平台?明理信息科技为你提供全程解决方案

明理信息科技saas知识付费平台 在当今数字化时代&#xff0c;知识付费已经成为一种趋势&#xff0c;越来越多的人愿意为有价值的知识付费。然而&#xff0c;公共知识付费平台虽然内容丰富&#xff0c;但难以满足个人或企业个性化的需求和品牌打造。同时&#xff0c;开发和维护…

在Java中高效使用Lambda表达式和流(Streams)的技巧

Java中如何高效使用Lambda表达式和流&#xff08;Streams&#xff09;的技巧 1. 简介 在Java中&#xff0c;Lambda表达式和流&#xff08;Streams&#xff09;是Java 8引入的两个强大的特性。Lambda表达式为Java添加了一种简洁的方式来实现函数式编程&#xff0c;而流提供了一…

为什么是60R+60R+电容,而不是直接用120R?

我们经常会在CAN通讯中看到如下所示的设计&#xff1a;CAN终端电阻不直接用120欧姆&#xff0c;而是用两个60欧姆串联&#xff0c;并且在两个电阻中间用一个小电容接地。 所以为什么这么做呢&#xff1f;难道说用一颗电阻不好吗&#xff1f;还可以节省点一些布局空间。 存在即…

【OpenGL/WebGL】Shader中如何获取摄像机视口的宽高

一、需求背景 在有些需求中&#xff0c;物体的大小是随着摄像机的视口的大小而变化的。如下图中&#xff0c;蓝色小方块&#xff0c;随着不断放大&#xff0c;其大小有个最大值&#xff0c;并不会无限放大。 这种实现的原理是在Shader中&#xff0c;不断根据摄像机近平面尺寸大…