循环中python排序方法的时间复杂度

时间:2017-11-03 14:42:26

标签: python time-complexity

def findEquals(words, word):
    wordCounts = sorted(Counter(word).values())
    equals = []

    for word in words:
        wordsCounts = sorted(Counter(word).values())
        if wordCounts == wordsCounts:
            equals.append(word)

    return equals

所以我在我的代码中有这个循环,其中单词是单词列表。对于列表中的每个单词,我将字母的频率存储在计数器中作为值,然后使用sorted()方法对其进行排序。我知道sorted()的时间复杂度最差为O(nlog(n))。我是否正确地说整个代码的最差时间复杂度是O(n ^ 2 log(n)),因为在for循环中使用sorted()?

2 个答案:

答案 0 :(得分:2)

  

我是否正确地说整个代码的最差时间复杂度是O(n ^ 2 log(n)),因为在for循环中使用sorted()?

不一定。确实,for循环是O(N),sorted是O(N log N),但这些表达式中的“N”指的是不同的值。 O(N)中的N指的是words的长度,O中的N(N log N)指的是word的长度。

如果每个word字符串的平均长度等于{{1}的长度,那么算法的总复杂度为O(N ^ 2 log N)是正确的。 }列表。例如,如果words包含五个单词,每个单词有五个字母。但事实并非如此。更一般的结论可能是算法是O(m * n log n),m对应于words的大小,n对应于单词的平均大小。

答案 1 :(得分:0)

这里的渐近分析会有点奇怪,因为正如你所写的那样,它实际上是三个输入的函数:干草堆,大海捞针中每个单词的长度,以及针。

为了使它更简单,你可以缓存针的排序值:这些是静态的(这个操作将被通过haystack的迭代所淹没)。

我还简化了使用过滤的代码,这将抽象出循环迭代。这对算法的性能没有理论上的影响,但返回迭代器会产生惰性结果,这可能会提高实际性能。

因为频率是整数,所以它们可以在O(n)中根据频率进行排序。

因此,对于大海捞针中的每个元素,您将对针的频率进行排序和比较。这将是O(n*m),其中n是haystack的大小,m是haystack中每个元素的大小。

因此,您的代码可以简化:

def find_same_frequency_distribution(haystack, needle):
    needle_counts = sorted(Counter(needle).values())
    return filter(lambda x: sorted(Counter(x).values()) == needle_counts, haystack)

>>> def find_same_frequency_distribution(haystack, needle):
...     needle_counts = sorted(Counter(needle).values())
...     return filter(lambda x: sorted(Counter(x).values()) == needle_counts, haystack)
...
>>> li = ["daddy", "mummy", "dddya", "foosa"]
>>> for e in find_same_frequency_distribution(li, "babdb"):
...     print(e)
...
daddy
mummy
dddya