此实现的运行时在字符串中查找k个最常见的重复单词

时间:2014-09-09 20:44:13

标签: java algorithm

这是我的算法:

(a)制作一个包含WordOccurrenceString sentence的{​​{1}}课程。我们假设int numberOfOccurrencessentence个单词。使这个类实现n,并首先使比较器为Comparable,然后(任意地)使numberOfOccurrences秒的字母(自然)排序。

(b)使用word遍历sentence(或者通过迭代进行迭代以节省空间)。为每个唯一字词创建一个新的.split(‘ ‘)对象,更新其出现次数并将所有WordOccurrence个对象放入WordOccurrence

(c)为每个唯一字词创建一个新的TreeMap<WordOccurrence>对象,将所有WordOccurrence个对象放入WordOccurrence(并在此过程中更新单词&#39;)。

(d)在TreeMap上调用TreeMap<WordOccurrence>,并将返回的单词放入结果列表中。然后使用先前返回的单词(k-1)次调用highestKey(),将单词放入相同的结果列表中。

(e)返回结果清单。

我的问题:这是什么运行时?这是我的理解:

步骤(b)花费O(n)时间。

步骤(c)取O(n * log(n)),对于n个单词中的每个单词,插入为O(log n)。

步骤(d)取O(k * log(n)),因为lowerKeyhighestKey()的每次调用都需要O(log n)时间。

因此总运行时间为:O(n + n * log(n)+ k * log(n),即O(n * log n)。

这个算法是否有更严格的约束,或者是将它转换为O(n)的方法?

感谢。

2 个答案:

答案 0 :(得分:0)

由于以下几个原因,你的方法很糟糕:

  • 襁褓中的所有东西都会使这里的常数因素不合理地高。你在字符串中为每个单词创建至少两个对象;鉴于平均英文单词是六个字母,你可以算出平均爆炸。
  • 您可以使用TreeMap<String, Integer>代替使用此WordOccurrence thingamajig。由于第一个原因,这仍然很糟糕,但它减少了你必须编写的代码量。
  • 您的推理没有考虑到键是字符串,因此是可变长度的事实。我不认为这会影响任何事情,但如果我是助教,我会把它标记下来。
  • 对于数据结构,我会使用哈希表。你可以在Java中使用HashMap,而你会得到更好的东西。你可能会看一下Trove或其他东西的HashMap,其值为int而不是Integer s。

此外,还有一种称为后缀树的数据结构。您可以在线性时间内在字符串上构建后缀树,并探索它以找出所有不同的单词和每个单词的计数。然后你可以做线性时间选择来找到前k个。这在实践中肯定会丢失到哈希表,但理论上它避免了常量时间查找哈希表。

答案 1 :(得分:0)

我相信你对此算法的分析很紧张。至于更严格的约束:
- 使用HashMap而不是TreeMap。现在步骤(c)在O(N)中运行。
- 在步骤(c)之后,创建一个TreeMap。
- 迭代HashMap中的条目。对于每个条目,将其添加到TreeMap。如果TreeMap的大小大于k,请调用remove(lastEntry())。

最后你有你想要的k个条目。由于TreeMap永远不会大于k + 1,因此运行时间复杂度为O(n)+ O(k * log(n))&lt;为O(n *的log(n))。