这是我的算法:
(a)制作一个包含WordOccurrence
和String sentence
的{{1}}课程。我们假设int numberOfOccurrences
有sentence
个单词。使这个类实现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)),因为lowerKey
或highestKey()
的每次调用都需要O(log n)时间。
因此总运行时间为:O(n + n * log(n)+ k * log(n),即O(n * log n)。
这个算法是否有更严格的约束,或者是将它转换为O(n)的方法?
感谢。
答案 0 :(得分:0)
由于以下几个原因,你的方法很糟糕:
TreeMap<String, Integer>
代替使用此WordOccurrence
thingamajig。由于第一个原因,这仍然很糟糕,但它减少了你必须编写的代码量。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))。