Given a non-empty list of words, return the k most frequent elements.
Your answer should be sorted by frequency from highest to lowest. If two words have the same frequency, then the word with the lower alphabetical order comes first.
Example 1:
Input: ["i", "love", "leetcode", "i", "love", "coding"], k = 2 Output: ["i", "love"] Explanation: "i" and "love" are the two most frequent words. Note that "i" comes before "love" due to a lower alphabetical order.
Example 2:
Input: ["the", "day", "is", "sunny", "the", "the", "the", "sunny", "is", "is"], k = 4 Output: ["the", "is", "sunny", "day"] Explanation: "the", "is", "sunny" and "day" are the four most frequent words, with the number of occurrence being 4, 3, 2 and 1 respectively.
Note:
- You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
- Input words contain only lowercase letters.
Follow up:
- Try to solve it in O(n log k) time and O(n) extra space.
通过HashMap和一个大小为k的堆实现,这里面堆的管理,与平时大小为k的堆的管理有些不一样,平时大多是先去除堆顶,再插入,本例中,因为涉及到字典序,所以应当先压堆,保证好堆序后,再去除堆顶,程序如下所示:
class Solution {
public List<String> topKFrequent(String[] words, int k) {
Map<String, Integer> map = new HashMap<>();
for (String s : words){
map.put(s, map.getOrDefault(s, 0) + 1);
}
PriorityQueue<String> que = new PriorityQueue<>(new Comparator<String>(){
@Override
public int compare(String s0, String s1){
if (map.get(s0) == map.get(s1)){
return s1.compareTo(s0);
}
return map.get(s0) - map.get(s1);
}
});
for (Iterator<Map.Entry<String, Integer>> ite = map.entrySet().iterator(); ite.hasNext(); ){
Map.Entry<String, Integer> entryset = ite.next();
if (que.size() < k){
que.offer(entryset.getKey());
}
else if (map.get(que.peek()) <= map.get(entryset.getKey())) {
que.offer(entryset.getKey());
que.poll();
}
}
List<String> res = new ArrayList<>();
while (!que.isEmpty()){
res.add(0,que.poll());
}
return res;
}
}