bisect.bisect_left 返回第一个≥target的索引,不保证等于target,需手动检查索引是否越界及对应元素是否等于target,否则易误判不存在。

bisect.bisect_left 返回插入位置,不等于“找到了”,必须手动校验元素是否存在。
用 bisect_left 判断元素是否存在时,为什么总返回 False 或越界?
因为 bisect_left 只负责找“第一个 ≥ target 的索引”,它不管那个位置上是不是真等于 target。比如对 [1, 3, 5] 查 4,它返回 2(指向 5),但 5 != 4。
- 必须检查索引是否
,否则查比最大值还大的数会触发 <code>IndexError - 必须额外写
arr[i] == x这一行比较——bisect模块本身不提供存在性判断函数 -
bisect_left([], x)返回0,此时i 为 <code>False,逻辑天然安全 - 别用
if bisect_left(arr, x) != -1:——该函数**永远不会返回 -1**,这个判断永远为真
在含重复元素的列表中,bisect_left 和 bisect_right 怎么配合用?
两者差值就是目标值出现次数,这是唯一干净获取频次的方式。
-
bisect_left(nums, x)返回最左可插位置(即首个x的索引,或第一个 ≥x的位置) -
bisect_right(nums, x)返回最右可插位置(即最后一个x后一位) - 所以
bisect_right(nums, x) - bisect_left(nums, x)就是x的出现次数 - 若只关心是否存在,用
bisect_left+ 校验更直觉;若要统计范围(如“分数在 80–90 之间的人数”),就组合两个函数
Python 3.10+ 新增的 key 参数怎么安全使用?
key 允许你按字段二分查找,但容易因 key 函数副作用或类型不一致出错。
-
key只作用于列表元素,**不会作用于查询值x**——你得自己确保x已是 key 提取后的类型 - 例如用
key=lambda d: d["score"],查85没问题,但不能查{"score": 85} - key 函数不能抛异常,也不能返回不可比较类型(如
None、dict);否则bisect会直接报TypeError - 如果列表是动态变化的,务必保证
key输出稳定——比如对 datetime 对象用.timestamp()比用.date()更稳妥,避免时区扰动
insort 看起来方便,为什么实际性能可能不如先 append 再 sort?
单次 insort 是 O(n),而多次调用会让总成本变成 O(n²),尤其当插入点靠前时。
-
insort_left(arr, x)=bisect_left(O(log n)) +list.insert(i, x)(O(n))——后者占主导 - 10⁴ 次随机插入,用循环
insort可能比arr.append(x)收集完再sorted(arr)慢一个数量级 - 仅当插入频率低、查找频率高、且需实时维持有序(如滑动窗口中位数)时,
insort才值得用 - 真要高频动态维护有序结构,改用
sortedcontainers.SortedList(支持 O(log n) 插入/查找)
真正容易被忽略的是:所有 bisect 调用都依赖输入列表严格升序且未被意外修改。一旦有人调了 arr.append(...) 或 arr.sort(reverse=True),后续所有 bisect 结果都不可信——模块不校验,也不修复。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











