我写了一个函数,它按顺序获取一个唯一整数列表的输入(从小到大)。我应该在列表中找到一个与索引中的值匹配的索引。例如,如果L [2] == 2,则输出为真。 所以在我复杂度O(logn)之后,我现在想要找到有多少索引的行为与给定列表中的行为相同,具有相同的复杂度O(logn)。 我上传我的第一部分代码,第一部分和第二部分我需要帮助:
def steady_state(L):
lower= 0
upper= len(L) -1
while lower<=upper:
middle_i= (upper+ lower)//2
if L[middle_i]== middle_i:
return middle_i
elif L[middle_i]>middle_i:
upper= middle_i-1
else:
lower= middle_i +1
return None
def cnt_steady_states(L):
lower= 0
upper= len(L) -1
a=b=steady_state(L)
if steady_state(L)== None:
return 0
else:
cnt=1
while True:
if L[upper] == upper and a<=upper:
cnt+= upper-a
upper= a
if L[lower]== lower and b>=lower:
cnt+= b- lower
lower = b
答案 0 :(得分:2)
你所提供的限制是不可能的。您理论上可以实现的最佳复杂性是 O ( n )。
O ()假设最坏的情况(只是一个定义,你可以放弃那个部分)。在最糟糕的情况下,总是必须查看每个项目,以便检查它是否等于其索引。
如果您有更多限制,案例会发生变化(例如,这些数字都是整数,而且没有一个可能出现多次,即没有两个连续的数字相等)。也许是这样的?
编辑:
在听说实际上我的假设限制适用后(即只出现一次)我现在提出这种方法:您可以放心地假设您只能拥有一个连续范围,其中所有匹配的条目都位于其中。 I. e。你只需要找到一个下限和上限。然后,想要的结果将是该范围的大小。
使用二进制搜索可以安全地找到每个绑定,其中每个都有 O (log n )。
def binsearch(field, lower=True, a=0, b=None):
if b is None:
b = len(field)
while a + 1 < b:
c = (a + b) / 2
if lower:
if field[c] < c:
a = c
else:
b = c
else: # search for upper bound
if field[c] > c:
b = c
else:
a = c
return b if lower else a
def indexMatchCount(field):
upper = binsearch(field, lower=False)
lower = binsearch(field, b=upper+1)
return upper - lower + 1
这是我用来测试的:
field = list({ random.randint(-10, 30) for i in range(30) })
field.sort()
upper = binsearch(field, lower=False)
lower = binsearch(field, b=upper+1)
for i, f in enumerate(field):
print lower <= i <= upper, i == f, i, f
答案 1 :(得分:1)
假设负整数正常:
我认为关键是如果你得到的值小于你的索引,你知道左边的所有索引也与它们的值不匹配(因为整数是严格增加的)。此外,一旦获得其索引值大于索引的索引,右侧的所有内容都不正确(原因相同)。然后,您可以像在第一种情况下那样进行分治算法。有点像:
check middle index:
if equal:
count = count + 1
check both halves, minus this index
elif value > index:
check left side (lower to index)
elif index > value:
check right side (index to upper)
在最坏的情况下(每个索引都匹配该值),我们仍然需要检查每个索引。
如果整数是非负数,那么你就会知道更多。您现在也知道如果索引与值匹配,则左侧的所有索引也必须与值匹配(为什么?)。因此,你得到:
check middle index:
if equal:
count = count + indices to the left (index-lower)
check the right side (index to upper)
elif value > index:
check left side (lower to index)
elif index > value:
##Can't happen in this case
现在我们最糟糕的情况得到了显着改善。我们没有找到匹配且没有从中获取任何新信息的索引,而是在找到匹配的索引时获得大量信息,现在知道一半的索引匹配。
答案 2 :(得分:1)
如果“所有数字都是整数且它们只出现一次”,那么您只需对L[i]==i && L[i+1]!=i+1
中的第一对数字进行二分搜索。
要允许否定整数,请检查是否L[0]<0
,如果是,请在1..N之间搜索:
i>0 && L[i]==i && L[i-1]!=i-1
。然后在i和N之间执行上一次搜索。