考虑到这个问题的一个简单实现,我正在寻找一种在Python列表中查找最常见单词的显著更快的方法。作为Python访谈的一部分,我收到了这样的反馈:这个实现效率太低,基本上是失败的。后来,我尝试了许多我发现的算法,只有一些基于heapsearch的解决方案更快一些,但并不是非常快(当扩展到数千万个项目时,heapsearch大约快30%;对于像千这样的琐碎长度,它几乎是一样的;使用timeit)。在
def stupid(words):
freqs = {}
for w in words:
freqs[w] = freqs.get(w, 0) + 1
return max(freqs, key=freqs.get)
因为这是一个简单的问题,而且我有一些经验(虽然我不是算法大师或竞争对手),我很惊讶。在
当然,我想提高我的技能,学习解决问题的更好方法,所以你的意见将不胜感激。在
重复状态的澄清:我的重点是找出是否真的有很多(渐进的)更好的解决方案,而其他类似的问题已经选择了一个不太好的答案。如果这还不足以使问题变得独特,当然,请关闭此问题。在
更新
谢谢大家的意见。关于面试的情况,我的印象是手写的搜索算法是被期待的(这可能会更有效一些)和/或评审员是从另一种语言的角度评估代码,有不同的常量因素。当然,每个人都可以有自己的标准。在
对我来说,重要的是验证我是否完全没有头脑(我的印象是我不是),或者只是通常写不出最好的代码。仍然有可能存在更好的算法,但如果它在这里为社区隐藏几天,我对此很满意。在
我选择了最有说服力的答案——这样做似乎公平,尽管不止一个人获得了有用的反馈。在
小更新
似乎使用defaultdict比使用“get”方法有明显的优势,即使它是静态别名。在
这听起来像是一个糟糕的面试问题,可能是面试官期待某个答案的情况。听起来他/她没有清楚地解释他/她在问什么。在
您的解决方案是
O(n)
(其中n = len(words)
),使用堆不会改变这一点。在有更快的近似解。。。在
函数调用和全局命名空间搜索的开销更大。在
您的
stupid
函数对单词列表中的每个元素进行2次函数调用。您的max
调用中的第二个是完全可以避免的,即迭代dict的键,然后对于每个键使用dict.get
查找值,当您可以迭代键值对时,这是一个明显的低效率。在使用user1952500的单通建议,这在您的大型样本集上表现如何?在
^{pr2}$对于多个最常见的值来说,这有一个小小的优点,即稳定。在
使用cd4{生成所有建议的样本:
结果:
注意事项:
multiprocessing.Pool
实例作为kwarg进行作弊,以达到计时目的,因为我想避免池的启动成本,timeit
不允许您指定清理代码。这是在一个“四”cpu虚拟机上运行的,我确信对于输入数据和cpu计数的某些值,多处理将更快。在n*m
的大值,应忽略版本6(一行程序)。在word_counter
是一个以单词为键、频率为值的字典,还有一个most_common()
方法。在相关问题 更多 >
编程相关推荐