是O(n)还是更大?
n
=列表长度
a
是一个很长的整数列表
final_count=0
while(n>1):
i=0
j=1
while(a[i+1]==a[i]):
i=i+1
j=j+1
if i==n-1:
break
for k in range(j):
a.pop(0)
final_count=final_count+j*(n-j)
n=n-j
答案 0 :(得分:1)
我看到它的方式,如果不是a.pop(0)
部分,你的代码将为O(n)。由于列表在内存中实现为数组,因此删除顶部的元素意味着数组中的所有元素也需要移动。因此,从列表中删除O(n)。你是在j
的循环中完成的,据我所知,最后,所有j
的总和将与n
相同,所以你要删除列表中的n
项,使该部分为二次方(O(n²))。
您可以通过不修改列表来避免这种情况,并且只是跟踪初始索引。这不仅消除了对pop的需求,而且还消除了对j
的循环,使得复杂度计算更直接:
final_count = 0
offset = 0
while n > 1:
i = 0
j = 1
while a[offset + i + 1] == a[offset + i]:
i += 1
j += 1
if i == n - 1:
break
offset += j
final_count += j * (n - j)
n = n - j
顺便说一下。我不清楚为什么你每次跟踪j
,因为j = i + 1
,所以你可以摆脱它,使代码更简单。如果您首先调整j * (n - j)
,那么最后j * n
正是n
:
final_count = 0
offset = 0
while n > 1:
i = 0
while a[offset + i + 1] == a[offset + i]:
i += 1
if i == n - 1:
break
offset += i + 1
n = n - (i + 1)
final_count += (i + 1) * n
最后一点:正如您可能注意到的那样,offset
现在从零开始计算到列表的长度,而n
正在反向,从列表的长度计算为零。你可以把它结合起来,所以你不需要两者。