给一非空的单词列表,返回前 k 个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。
示例 1:
输入: ["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 次。
注意:
假定 k 总为有效值, 1 ≤ k ≤ 集合元素数。
输入的单词均由小写字母组成。
扩展练习:
尝试以 O(n log k) 时间复杂度和 O(n) 空间复杂度解决。
class Solution {
public:
void swap(int x,int y){
string t=str[x];
str[x]=str[y];
str[y]=t;
}
void down(int i,int n){
int parent=i;
int child=2*parent+1;
while(child<n){
if(child+1<n&&m[str[child]]<m[str[child+1]]){
child++;
}
else if(child+1<n&&(m[str[child]]==m[str[child+1]])&&(str[child]>str[child+1])){
child++;
}
if(m[str[child]]>m[str[parent]]){
swap(parent,child);
parent=child;
}
else if((m[str[child]]==m[str[parent]])&&(str[child]<str[parent])){
swap(parent,child);
parent=child;
}
child=2*child+1;
}
}
vector<string> topKFrequent(vector<string>& words, int k) {
m.clear();
str.clear();
int n=words.size();
size=0;
for(string word:words){
m[word]++;
}
for(map<string,int>::iterator it=m.begin();it!=m.end();it++){
str.push_back(it->first);
size++;
}
for(int i=size/2-1;i>=0;i--){
down(i,size);
}
for(int i=1;i<=k;i++){
swap(0,size-i);
down(0,size-i);
}
vector<string>v;
for(int i=size-1;i>=size-k;i--){
v.push_back(str[i]);
}
return v;
}
map<string,int>m;
vector<string>str;
int size;
};
class Solution {
public:
vector<string> topKFrequent(vector<string>& words, int k) {
map<string, int>m;
for(string word: words) m[word]++;
priority_queue<pair<int, string>> q;
for(auto [str, cnt]: m){
q.push({-cnt, str});
if(q.size()>k) q.pop();
}
vector<string>v;
while(!q.empty()){
v.push_back(q.top().second);
q.pop();
}
reverse(v.begin(), v.end());
return v;
}
};