692. 前K个高频单词
难度:中等
语言:java
题目内容
给一非空的单词列表,返回前 k 个出现次数最多的单词。
返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率,按字母顺序排序。
解法分析
这个很容易能够想到哈希表的方法来记录出现次数,主要还有个按照字母顺序排序的要求。有两种解法可以解决,一个是排序解法,还有一种是小根堆,小根堆在最近的题目中出现蛮多次的,是一种比较简单的排序方法。
先看排序的解法,使用ArrayList的lambda排序方法来进行排序,这是一个比较简单的方法打,JDK8带来的lambda表达式,让List的排序简单了非常多:
class Solution {
public List<String> topKFrequent(String[] words, int k) {
Map<String,Integer> ansmap = new HashMap<>();
for (String s:words){
ansmap.put (s,ansmap.getOrDefault(s,0)+1);
}
List<String> ans = new ArrayList<>(ansmap.keySet());
ans.sort((a, b) -> {
if (ansmap.get(a).equals(ansmap.get(b))) {
return a.compareTo(b);
} else {
return ansmap.get(b) - ansmap.get(a);
}
});
return ans.subList(0, k);
}
}
接下来再来看小根堆的方法,这个方法我之前没学会写,就借鉴一下答案来看。
public class Solution {
public List<String> topKFrequent(String[] words, int k) {
// 1.先用哈希表统计单词出现的频率
Map<String, Integer> count = new HashMap();
for (String word : words) {
count.put(word, count.getOrDefault(word, 0) + 1);
}
// 2.构建小根堆,相比List,这里可以直接写出排序规则,跟List也类似
PriorityQueue<String> minHeap = new PriorityQueue<>((s1, s2) -> {
if (count.get(s1).equals(count.get(s2))) {
return s2.compareTo(s1);
} else {
return count.get(s1) - count.get(s2);
}
});
// 3.依次向堆加入元素。
for (String s : count.keySet()) {
minHeap.offer(s);
// 当堆中元素个数大于 k 个的时候,需要弹出堆顶最小的元素。
if (minHeap.size() > k) {
minHeap.poll();
}
}
// 4.依次弹出堆中的 K 个元素,放入结果集合中。
List<String> res = new ArrayList<String>(k);
while (minHeap.size() > 0) {
res.add(minHeap.poll());
}
// 5.注意最后需要反转元素的顺序。
Collections.reverse(res);
return res;
}
}
其实看完了这个方法,并没有觉得简单很多,但是空间是节省了的,因为堆相比List所使用的空间只有O(K)