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()?
答案 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