假设我有一个Floats排序列表。现在我想获得给定值的下一个较低项的索引。通常的for-loop aprroach具有O(n)的复杂性。由于列表已排序,因此必须有一种方法可以使用O(log n)获取索引。
我的O(n)方法:
index=0
for i,value in enumerate(mylist):
if value>compareValue:
index=i-1
是否有用于解决O(log n)中的问题的数据类型?
最好的问候 塞巴斯蒂安答案 0 :(得分:15)
bisect怎么样?
>>> import bisect
>>> float_list = [1.0, 1.3, 2.3, 4.5]
>>> i = bisect.bisect_left(float_list, 2.5)
>>> index = i - 1
>>> index
2
您可能必须单独处理搜索值小于或等于列表中最低/最左侧值的情况(在这种情况下为index == -1
)。
根据您在平等的情况下希望拥有的索引,您可能不得不使用bisect_right
。
答案 1 :(得分:10)
您可以对数组/列表执行二进制搜索以获取您正在查找的对象的索引,并获取其下方的索引以获取较低的条目(假设实际上存在较低的条目!)。< / p>
答案 2 :(得分:2)
答案 3 :(得分:2)
import bisect
def next_lower_value(values_list, input_value):
index= bisect.bisect_left(values_list, input_value)
if index == 0: # there's not a "next lower value"
raise NotImplementedError # you must decide what to do here
else:
return values_list[index - 1]
>>> l= [11, 15, 23, 28, 45, 63, 94]
>>> next_lower_value(l, 64)
63
>>> next_lower_value(l, 63)
45
>>> next_lower_value(l, 1000)
94
>>> next_lower_value(l, 1)
Traceback (most recent call last):
File "<pyshell#29>", line 1, in <module>
next_lower_value(l, 1)
File "<pyshell#26>", line 4, in next_lower_value
raise NotImplementedError # you must decide what to do here
NotImplementedError
由于您请求索引而不是下一个较低的值,请将函数next_lower_value
更改为返回index - 1
而不是values_list[index - 1]
。
答案 4 :(得分:1)
回答关于数据类型的部分问题:在一般意义上,最适合在O(log n)时间内查找事物的数据类型(在插入和删除时保持O(1)性能!)是二叉树。您可以通过做出一系列左右决定来查找其中的内容,这非常类似于您在线性列表中进行二进制搜索的方式,但(IMO)在概念上更直观。
也就是说,从我对Python的了解很少,二叉树似乎不在语言的标准库中。对于您的应用程序,仅为此目的包含实现可能没有任何好处。
最后,排序列表中的二叉树和二进制搜索将允许您将搜索缩短一步:没有必要搜索关键项,然后返回其前一个。相反,在每个比较步骤中,如果遇到键值,就好像它太大了。这将导致您的搜索结束下一个较小的值。仔细完成,这也可能有助于bart提到的“几乎相等的浮点值”问题。
答案 5 :(得分:1)
如果我正确读取此项,则下一个较低的项目是列表中第一个小于或等于x的项目。 bisect documentation for searching sorted lists提供了此功能:
def find_le(a, x):
'Find rightmost value less than or equal to x'
i = bisect_right(a, x)
if i:
return a[i-1]
raise ValueError
答案 6 :(得分:0)
def lower_bound(arr, x):
left = 0
right = len(arr)-1
mid = -1
if(arr[left] > x):
return mid
while(left <= right):
mid = int(left + (right - left + 1) / 2)
if(left == right and right == mid):
return mid
if(x > arr[mid]):
left = mid
elif(x < arr[mid]):
right = mid - 1
else:
return mid
return mid
如果找到了精确的元素,则此函数返回已排序列表“ arr”中元素的索引,否则返回小于给定数字“ x”的最大元素的索引。如果没有元素小于给定的数字,则返回-1。