【问题标题】:Word Frequency - HashMap or TreeMap词频 - HashMap 或 TreeMap
【发布时间】:2013-12-11 16:00:31
【问题描述】:

我需要制作一个程序来计算文本中每个单词的频率,另外我需要能够返回 n 个最常用单词的列表(如果更多的词具有相同的频率,它们按字母顺序排序)。还有一个不计算的单词列表(停用词)。

  1. 停用词使用什么结构
    • 我认为 HashSet 效率最高
  2. 单词和频率映射使用什么结构
    • HashMap 添加单词会更高效,但需要排序,TreeMap 插入单词需要 logn 时间,但单词可以按频率排序

总体而言,哪种方法更有效?

附: @Moderators 我知道有一个类似的question,但我有不同的约束,需要不同的结构。

【问题讨论】:

  • 您的问题与您所指的问题有何不同?它看起来完全相似,并且该问题的公认答案也回答了您的问题。
  • @Roman 我不需要“按字母顺序打印每个唯一的单词”,我必须得到 k 最常用的单词。所以 treeMap 不是显而易见的解决方案。

标签: java data-structures map hashmap treemap


【解决方案1】:

假设总共有k 个词和m 个不同的词,并且您想要n 最常见的词。

树图

由于地图中的单词永远不会超过m,因此每次更新/插入将花费O(log m),总运行时间为O(k log m)

HashMap

每次更新/插入都将花费预期的O(1),所有单词都需要O(k)

那么,由于地图中有m字样,排序将采用O(m log m)

但我们可以做得比排序更好——我们可以遍历HashMap 并维护n 最常用词的heap (PriorityQueue)(主要按频率排序,其次按字母顺序排序)。每次插入堆后,如果大小大于n,我们删除最不常见的单词。这需要O(m log n)

因此,预计总运行时间O(k + m log n)

比较

由于n <= mm <= k,我们知道m log n <= k log m,并且假设有很多重复或nmk + m log n <= k log m略小,所以HashMap一般是首选。

【讨论】:

    【解决方案2】:

    停用词:HashSet 或正则表达式。

    我会使用哈希图来计算频率:

    1. 你的词域 w 是(或多或少)有限的
    2. 您的输入大小 n (大概)是无限的

    所以你会做很多插入。 HashMap 的总插入成本:O(n),TreeMap 的总插入成本:O(n log w)

    哈希图的排序成本:O(w log w),加上提取开销O(w)。即使 TreeMap 为零,对于较大的 nO(w log w) 也会变得非常小。

    请注意,一般情况下,如果不对两者进行基准测试,就无法保证解决此问题。

    【讨论】:

    • 问题是你不能就地对 HashMap 进行排序。如果它太大了以至于你关心性能,那么将它复制到数组对你来说是一个相当大的问题。
    • 我们在这里讨论字数。这些不会超过几万(可能,除非它是一种凝聚语言),所有这些都由引用表示。所以我不认为这对于复制和就地排序来说太大了。不过,我同意我的回答最适合大型 n 并且如果您是例如对嵌入式设备上的小 n 执行此操作。不过,这似乎不是最有可能的平台。
    【解决方案3】:

    您可以对计数/单词的最终 HashMap<String, Integer> 执行单次传递,并使用 TreeMap<Integer, List<String>>TreeMap.firstKey()TreeMap.size() 方法计算前 N 个单词。练习留给读者。或者(或更好),使用像 this one 这样的红黑树,当您发现计数更大时(当树的大小在前 N 中 > N 时),您会不断修剪最低计数节点。

    【讨论】:

      猜你喜欢
      • 2011-10-26
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 2011-02-22
      • 2013-10-31
      • 2017-08-28
      • 2018-06-06
      • 2015-09-01
      相关资源
      最近更新 更多