python标准库
8 数据类型
目标:使用一个基础的二分查找算法维护一个有序List。
可使用函数:
-
bisect.bisect_left(a, x, lo=0, hi=len(a))
a是有序List,返回的索引是第一个等于x的第一个或大于x的第一个索引。lo和hi是取出a中的一部分。
返回的索引i满足 左边 all(val < x for val in a[lo:i])
右边 all(val >= x for val in a[i:hi]) -
bisect.bisect_right(a, x, lo=0, hi=len(a))
bisect.bisect(a, x, lo=0, hi=len(a))
a是有序List,返回的索引是大于x的第一个索引。lo和hi是取出a中的一部分。
返回的索引i满足 左边 all(val <= x for val in a[lo:i])
右边 all(val > x for val in a[i:hi]) -
bisect.insort_left(a, x, lo=0, hi=len(a))
等价于 a.insert(bisect.bisect_left(a, x, lo, hi), x) -
bisect.insort_right(a, x, lo=0, hi=len(a))
bisect.insort(a, x, lo=0, hi=len(a))
等价于 a.insert(bisect.bisect_right(a, x, lo, hi), x)
举例:
def index(a, x):
# 定位最左边的x'
i = bisect_left(a, x)
if i != len(a) and a[i] == x:
return i
raise ValueError
def find_lt(a, x):
'val<x的集合'
i = bisect_left(a, x)
if i:
return a[:i-1]
raise ValueError
def find_le(a, x):
'val<= x的集合'
i = bisect_right(a, x)
if i:
return a[:i-1]
raise ValueError
def find_gt(a, x):
' val > x的集合
i = bisect_right(a, x)
if i != len(a):
return a[i:]
raise ValueError
def find_ge(a, x):
# val >= x的集合
i = bisect_left(a, x)
if i != len(a):
return a[i:]
raise ValueError
# 分数排名,0-59:F,60-69:D , 70-79:C , 80-89:B , 90-> A
>>> def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
i = bisect(breakpoints, score)
return grades[i]
# 返回score在breakpoints的右索引,始终是>score的。
>>> [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
#对于70,77返回的都是2-C;对于90,99,100,返回的都是4-A;对于小于60的始终取A
['F', 'A', 'C', 'C', 'B', 'A', 'A']
函数解析
def bisect_left(a, x, lo=0, hi=None):
"""a是有序List,返回的索引是第一个等于x的第一个或大于x的第一个索引。
lo和hi是取出a中的一部分。
返回的索引i满足 左边 all(val < x for val in a[lo:i])
右边 all(val >= x for val in a[i:hi])
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if a[mid] < x: lo = mid+1
#相等时让hi降下来
else: hi = mid
return lo
def bisect_right(a, x, lo=0, hi=None):
"""a是有序List,返回的索引是第一个大于x的第一个索引。
lo和hi是取出a中的一部分。
返回的索引i满足 左边 all(val <= x for val in a[lo:i])
右边 all(val > x for val in a[i:hi])
"""
if lo < 0:
raise ValueError('lo must be non-negative')
if hi is None:
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
if x < a[mid]: hi = mid
# 相等时让lo升下来
else: lo = mid+1
return lo