[英]Word Frequency - HashMap or TreeMap
我需要制作一个计算文本中每个单词频率的程序,另外我需要能够返回n个最常用单词的列表(如果更多的单词具有相同的频率,则按字母顺序排序)。 还有一个不计算的单词列表(停用词)。
总体来说哪种方法更有效?
PS @Moderators我知道有一个类似的问题 ,但我有一个不同的约束,需要不同的结构。
让我们假设总共有k
单词和m
不同的单词,你想要n
最常用的单词。
TreeMap的
由于地图中永远不会超过m
单词,因此每个更新/插入将花费O(log m)
,总运行时间为O(k log m)
。
HashMap中
每次更新/插入将花费预期的O(1)
,对所有单词取O(k)
。
然后,由于地图中将有m
单词,因此排序将采用O(m log m)
。
但是我们可以做得比排序更好 - 我们可以遍历HashMap
并维护n
最常用词的堆 ( PriorityQueue
)(主要按频率排序,其次按字母顺序排序)。 每次插入堆后,如果大小大于n
,我们删除最不频繁的单词。 这将花费O(m log n)
。
因此,预计总运行时间为O(k + m log n)
。
对照
由于n <= m
且m <= k
,我们知道m log n <= k log m
,并且假设有大量重复或n
略小于m
, k + m log n <= k log m
,所以HashMap
通常是首选的选项。
停用词:HashSet或regexp。
我会使用哈希映射来计算频率计数:
所以你会做很多插入。 HashMap的总体插入成本: O(n) ,对于TreeMap: O(n log w) 。
散列映射的成本: O(w log w) ,加上提取开销O(w) 。 即使TreeMap为零,对于大n , O(w log w)也会变得非常小。
请注意,一般情况下,没有保证的方法可以在没有基准测试的情况下解决这个问题。
您可以对计数/单词的最终HashMap<String, Integer>
执行单次传递,并使用TreeMap<Integer, List<String>>
和TreeMap.firstKey()
和TreeMap.size()
方法计算前N个话。 练习留给读者。 或者(或更好),使用像这样的红黑树,当您发现较大的计数时(当您的前N中树的大小> N时),您不断修剪最低计数节点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.