时间复杂度为O(n Log k),所以我们可以用O(n Log k)的时间复杂度来计算。
from collections import Counter
from heapq import heappush, heappop
class Pair:
def __init__(self, word, freq):
self.word = word
self.freq = freq
def __lt__(self, p):
return self.freq < p.freq or (self.freq == p.freq and self.word > p.word)
class Solution:
def topKFrequent(self, words: List[str], k: int) -> List[str]:
cnt = Counter(words)
h = []
for word, freq in cnt.items():
heappush(h, Pair(word, freq))
if len(h) > k:
heappop(h)
return [p.word for p in sorted(h, reverse=True)]
我理解这里发生的大部分事情,唯一不明白的是__lt__
方法,我理解我们正在覆盖__lt__
方法,但是它是如何在这里实现的?它是如何被调用的?
我最好的猜测是大多数调用都是在“隐蔽”下完成的。也就是说,当新的Pair对象被推到堆上时,__lt__
将被调用来比较频率,因为它返回一个布尔值,取决于返回值是True还是False,堆将相应地调整?
但是,当我们使用sorted()
时,在最后一个return语句中是否再次调用了__lt__
?
这个问题要求我们返回频率最高的前K个单词,如果有一个平局(单词有相同的频率),然后对这些单词进行字典排序。我试图理解排序到底是在哪里完成的?似乎频率排序和字典排序都是在__lt__
方法中完成的?
我浏览了代码,并使用调试器查看代码的执行顺序。我似乎无法弄清楚魔术方法(__lt__
)是如何/何时起作用的,以及何时进行字典排序。
我已经找到了一些以前讨论这个问题的线程,但无法找到解释/答案,从而阐明__lt__
方法。
2条答案
按热度按时间zf9nrax11#
lt
是小写的LT
而不是It
。lt代表“lessthan”。每当进行<
比较时,都会调用__lt__
方法。例如,x < y
将在后台调用x.__lt__(y)
。我不完全确定,但我的猜测是sorted()
函数使用__lt__
来比较和排序列表中的项。ukqbszuj2#
lt__是为python表达式中的
<
符号调用的dunder(魔术方法)。heapq在内部使用
<
符号来重新调整每次向堆中添加元素时的列表。您可以在heapq模块的python源代码库中找到它。我不能评论如何在内部排序(即,它是否使用__lt),但我假设它使用__lt__,否则我们将无法获得堆的排序列表。