
692. 前K个高频单词
给定一个单词列表 words
和一个整数 k
,返回前 k
个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。
示例 1:
输入: words = ["i", "love", "leetcode", "i", "love", "coding"], k = 2
输出: ["i", "love"]
解析: "i" 和 "love" 为出现次数最多的两个单词,均为2次。
注意,按字母顺序 "i" 在 "love" 之前。
示例 2:
输入: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4
输出: ["the", "is", "sunny", "day"]
解析: "the", "is", "sunny" 和 "day" 是出现次数最多的四个单词,
出现次数依次为 4, 3, 2 和 1 次。
注意:
1 <= words.length <= 500
1 <= words[i] <= 10
words[i]
由小写英文字母组成。k
的取值范围是[1, 不同 words[i] 的数量]
**进阶:**尝试以 O(n log k)
时间复杂度和 O(n)
空间复杂度解决。
解题思路:哈希表 + 优先级队列
这道题很明显还是要使用 topk
问题的处理方式来解决,也就是使用堆来解决,只不过这道题稍微要多处理其它的内容!
首先因为需要按单词出现频率由高到低排序,那么就需要统计单词的出现频率,就可以 使用哈希表来统计!
然后将哈希表内容按 topk
模式进行处理,这里有细节,就是因为我们既要获得堆中的字符串,又得根据频次来维护堆,所以优先级队列存放的是一个键值对 pair<string, int>
,还有就是因为==频次从高到小排序,那么我们就要建立一个小根堆==,所以要自己写一个比较器 compare
,这里用仿函数为例!
在比较器中还要特别注意一个细节,我们需要特殊判断一下次数相等的情况,此时要根据字典顺序从低到高排序,所以 对于字典序列要搞个大堆才行,和频次是相反的,一定要弄清楚比较器中大于和小于的区别,大于表示的是建小堆,小于表示的是建大堆,别搞错了!
接着就是一个循环,先将哈希表中的键值对插入,然后判断一下优先级队列是否超过了 k
个元素,是的话直接让堆顶 pop
掉即可,因为我们建立的堆是与序列相反的,那么 pop
的就是不满足要求的!以此类推,直到哈希表遍历完毕!
最后就是将堆中元素取出,然后放到数组中返回,注意因为堆中次序和返回的次序是相反的,所以我们要先逆序,再返回结果!
struct compare
{
bool operator()(pair<string, int>& p1, pair<string, int>& p2)
{
// 特殊判断一下次数相等的情况
if(p1.second == p2.second)
return p1.first < p2.first; // 注意细节,字典顺序是从低到高,所以字典要搞个大堆才行,和频次相反
return p1.second > p2.second;
}
};
class