我试图用Python编写一个函数,该函数在排序列表中查找第一个数字,该数字大于作为参数传递的特定值。我在网上找到了使用简单列表推导来实现此目的的示例,但是出于我的目的,我需要经常在大型列表上执行此操作,因此以线性时间运行的搜索过于昂贵。
我在编写类似于迭代的二进制搜索的函数来实现此目的方面遇到了麻烦,尽管我遇到了一些无法正常工作的情况。顺便说一句,该功能不需要处理列表中没有较大项目的情况。这是我现有的功能:
def findFirstLarger(num, sortedList): low = 0; high = len(sortedList) - 1 mid = -1 while True: print("low: " + str(low) + "\t high: " + str(high)) if (low > high): print("Ah geez, low is " + str(low) + " and high is " + str(high)) return # debugging, don't want this to happen if low == high: return sortedList[low] else: mid = (low + high) / 2; if num == sortedList[mid]: return sortedList[mid] elif num > sortedList[mid]: low = mid + 1 else: high = mid - 1
我已经注意到该功能不起作用的一种情况如下:
>>> somenumbers=[n*2 for n in range(131072)] >>> somenumbers[-5:] [262134, 262136, 262138, 262140, 262142] >>> binsearch.findFirstLarger(262139,somenumbers) low: 0 high: 131071 low: 65536 high: 131071 low: 98304 high: 131071 low: 114688 high: 131071 low: 122880 high: 131071 low: 126976 high: 131071 low: 129024 high: 131071 low: 130048 high: 131071 low: 130560 high: 131071 low: 130816 high: 131071 low: 130944 high: 131071 low: 131008 high: 131071 low: 131040 high: 131071 low: 131056 high: 131071 low: 131064 high: 131071 low: 131068 high: 131071 low: 131070 high: 131071 low: 131070 high: 131069 Ah geez, low is 131070 and high is 131069
此处的正确结果将是262140,因为这是列表中的第一个数字大于262139。
262140
262139
谁能推荐一个更清洁的实施方案,实际可行?我认为这不会是一个深奥的问题,尽管到目前为止我还无法在任何地方找到解决方案。
您是否尝试过该bisect模块?
bisect
def find_ge(a, key): '''Find smallest item greater-than or equal to key. Raise ValueError if no such item exists. If multiple keys are equal, return the leftmost. ''' i = bisect_left(a, key) if i == len(a): raise ValueError('No item found with key at or above: %r' % (key,)) return a[i] find_ge(somenumbers, 262139)
您的代码错误(1)low > high是有效的终止情况。(2)你不应该停留在low == high,例如,当它会返回一个不正确的索引num == 3你的somenumbers。
low > high
low == high
num == 3
somenumbers