这段代码的大O符号是什么?

时间:2015-07-25 13:51:28

标签: python algorithm time-complexity

是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

1 个答案:

答案 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正在反向,从列表的长度计算为零。你可以把它结合起来,所以你不需要两者。