二分查找
二分查找的前提是有序,有序的线性表,如果是字典,关键字有序
二分查找的时间复杂度是O(log n),在查找方法中是较常见的方法
假设有一个列表[37,99,73,48,47,63,35,37,37,37,90],先排序,再插入数字,使用python该怎样写呢,以下是一种解法
a = [37,99,73,48,47,63,35,37,37,37,90] newlist = sorted(a)##先排序 def inster_sort(orderlist, num): ret = orderlist[:] start = 0 end = len(ret) ##这里不能是len(ret)-1,如果要插入的数字大于最后一位,那么要返回的插入点要包含在范围内,不减一就能包含最后一个对象 while start < end: #两端会逐渐逼近,最终会重合 midpoint = (end + start) // 2 ##二分 if ret[midpoint] > num: end = midpoint ##要插入的数小于中点,右侧左移 else: start = midpoint+1 ##大于中点,左侧右移 ret.insert(start, num) return ret print(inster_rsort(newlist,100))##测试
当然,也可以反向倒排,原理相同,如下
a = [37,99,73,48,47,63,35,37,37,37,90] newlist = sorted(a,reverse=True) def inster_rsort(rorderlist,x): low = len(rorderlist) high = 0 while high != low: mid = (high+low)//2 if rorderlist[mid] > x: high = mid+1 else: low = mid rorderlist.insert(high,x) return rorderlist print(inster_rsort(newlist,100))##测试
当然,还可以写成递归版本,但是受递归深度限制,不推荐使用,效率也可能不好,有时间回来补递归版本!
bisect模块
bisect的函数有
bisect.bisect_left(a,x,lo=0,hi=len(a)) a是有序列表,x是要插入的对象,lo和hi指定区间,默认是整个区间,如果x存在,就返回x左边的index
bisect.bisect_right(a,x,lo=0,hi=len(a)) 和上边相同,只是返回的插入点如果已存在,就返回插入点右边的index
bisect.insort_left(a,x,lo=0,hi=len(a)) 有序列表a插入x,等同于a.insert(bisect.bisect_left(a,x),x)
bisect.insort_right() x存在时,在右边插入,
默认的存在x时,都是右边插入
小练习
一批工件,标准尺寸是20-22(练习忽略单位)为A级,18-20和22-24为B级,其他为C级,使用该模块解决,要求不包括边界
import bisect def get_gread(size): sizepoint = [18,20,22,24] greadlist = 'CBABC' if size<21: return greadlist[bisect.bisect_left(sizepoint,size)] else: return greadlist[bisect.bisect_right(sizepoint, size)]