1. 简介
在刷leetcode的时,我们经常会遇到需要处理有序序列,通常需要在其中进行查找、插入等操作。而 Python 中的 bisect
模块提供了一种高效的方法来处理这些操作。它主要用于在有序序列中查找某个元素的位置,或者在不破坏原有顺序的情况下插入新的元素。bisect
模块的设计简单而强大,使得我们能够以高效的方式处理大量数据,尤其是在算法和数据处理领域。
下面是简单的二分查找算法的示例:
a = [1,3,5,6,7,9]
def bisect(a, x):
left, right = 0, len(a) - 1
while left <= right:
mid = (left + right) // 2
if a[mid] < x:
left = mid + 1
elif a[mid] > x:
right = mid - 1
else:
return mid
return -1
print(bisect(a,4))
print(bisect(a,5))
bisect
提供了更为强大的方法,例如它能够查找不存在元素应该排序的位置,以及在重复元素中第一个与最后一个位置。
2. 模块概览
bisect
模块提供了一些函数,主要用于处理有序序列。其中最常用的是 bisect_left()
和 bisect_right()
函数,用于查找元素应该插入的位置,保证序列的有序性。此外,还有 insort_left()
和 insort_right()
函数,用于在插入元素的同时保持序列的有序性。这些功能使得 bisect
模块在处理大型数据集合时非常实用,尤其是在需要频繁查找和插入元素的情况下。
接下来我将详细介绍这些函数的用法,以及它们在实际应用中的示例和效果。
3. 主要函数介绍
bisect
模块是 Python 中用于处理有序序列的一个重要工具。它提供了一系列函数,用于在有序序列中进行查找和插入操作,以及维护序列的有序性。主要的函数包括:
bisect_left(a, x, lo=0, hi=len(a), *, key=None)
: 在有序序列a
中查找元素x
应该插入的位置,返回最左侧的位置,保持序列的有序性。
# 返回第一个5的位置
>>> a = [1,3,5,5,5,6,7,7,9]
>>> bisect_left(a, 5)
>>> bisect.bisect_left(a, 5)
2
bisect_right(a, x, lo=0, hi=len(a), *, key=None)
等价于bisect(a, x, lo=0, hi=len(a), *, key=None)
在有序序列a
中查找元素x
应该插入的位置,返回最右侧的位置,保持序列的有序性。
# 返回最后一个5的下一个位置
>>> bisect.bisect_right(a, 5)
5
>>> bisect.bisect(a, 5)
5
# 当不存在该元素时,bisect_left和bisect_right是相同的
# [1, 3, 4, 5, 5, 5, 5, 6, 7, 7, 9]
>>> bisect.bisect_left(a,8)
10
>>> bisect.bisect_right(a,8)
10
insort_left(a, x, lo=0, hi=len(a), *, key=None)
: 在有序序列a
中插入元素x
,并保持序列的有序性,插入位置为最左侧。
>>> bisect.insort_left(a, 4)
>>> a
[1, 3, 4, 5, 5, 5, 6, 7, 7, 9]
insort_right(a, x, lo=0, hi=len(a), *, key=None)
等价于insort(a, x, lo=0, hi=len(a), *, key=None)
在有序序列a
中插入元素x
,并保持序列的有序性,插入位置为最右侧。
>>> bisect.insort_right(a, 5)
>>> a
[1, 3, 4, 5, 5, 5, 5, 6, 7, 7, 9]
这些函数提供了高效的方法来处理有序序列,特别是在需要频繁进行查找和插入操作时。bisect
模块的应用领域广泛,常见于算法设计、数据处理以及搜索和排序等领域。其简单易用的接口和高效的实现使得它成为 Python 编程中不可或缺的一部分。
bisect
中key
参数的使用方式与sorted
的使用方式类似,其是自定义比较:
例如在一个有序的字典中我们想查找value
是否存在:
在 3.10 版本发生变更: 增加了 key 形参。
import bisect
data = {'banana': 1, 'cherry': 4, 'date': 6, 'apple': 8}
idx = bisect.bisect_left(list(data.items()), 4, key = lambda x: x[1])
print(idx)
1
python中bisect.py源码
"""Bisection algorithms."""
def insort_right(a, x, lo=0, hi=None, *, key=None):
"""Insert item x in list a, and keep it sorted assuming a is sorted.
If x is already in a, insert it to the right of the rightmost x.
Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
A custom key function can be supplied to customize the sort order.
"""
if key is None:
lo = bisect_right(a, x, lo, hi)
else:
lo = bisect_right(a, key(x), lo, hi, key=key)
a.insert(lo, x)
def bisect_right(a, x, lo=0, hi=None, *, key=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(i, 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.
A custom key function can be supplied to customize the sort order.
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
# Note, the comparison uses "<" to match the
# __lt__() logic in list.sort() and in heapq.
if key is None:
while lo < hi:
mid = (lo + hi) // 2
if x < a[mid]:
hi = mid
else:
lo = mid + 1
else:
while lo < hi:
mid = (lo + hi) // 2
if x < key(a[mid]):
hi = mid
else:
lo = mid + 1
return lo
def insort_left(a, x, lo=0, hi=None, *, key=None):
"""Insert item x in list a, and keep it sorted assuming a is sorted.
If x is already in a, insert it to the left of the leftmost x.
Optional args lo (default 0) and hi (default len(a)) bound the
slice of a to be searched.
A custom key function can be supplied to customize the sort order.
"""
if key is None:
lo = bisect_left(a, x, lo, hi)
else:
lo = bisect_left(a, key(x), lo, hi, key=key)
a.insert(lo, x)
def bisect_left(a, x, lo=0, hi=None, *, key=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(i, 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.
A custom key function can be supplied to customize the sort order.
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
# Note, the comparison uses "<" to match the
# __lt__() logic in list.sort() and in heapq.
if key is None:
while lo < hi:
mid = (lo + hi) // 2
if a[mid] < x:
lo = mid + 1
else:
hi = mid
else:
while lo < hi:
mid = (lo + hi) // 2
if key(a[mid]) < x:
lo = mid + 1
else:
hi = mid
return lo
# Overwrite above definitions with a fast C implementation
try:
from _bisect import *
except ImportError:
pass
# Create aliases
bisect = bisect_right
insort = insort_right