求出现频率最多的k个单词
1、使用优先队列解法
public List<String> topKFrequent(String[] words, int k) {
List<String> res = new ArrayList<>();
Map<String, Integer> map = new HashMap<>();
for (String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
PriorityQueue<Map.Entry<String, Integer>> q = new PriorityQueue<>(
(o1, o2) -> {
if (o1.getValue() == o2.getValue()) return o2.getKey().compareTo(o1.getKey());
return Integer.compare(o1.getValue(), o2.getValue());
}
);
for (Map.Entry<String, Integer> entry : map.entrySet()) {
q.offer(entry);
if (q.size() > k) q.poll();
}
while(!q.isEmpty()) res.add(0, q.poll().getKey());
return res;
}
2、bucket&trie排序(值得学习)
//https://leetcode.com/problems/top-k-frequent-words/discuss/108399/Java-O(n)-solution-using-HashMap-BucketSort-and-Trie-22ms-Beat-81
public List<String> topKFrequent(String[] words, int k) {
List<String> res = new ArrayList<>();
//统计单词出现个数
Map<String, Integer> map = new HashMap<>();
for (String word : words) {
map.put(word, map.getOrDefault(word, 0) + 1);
}
//建桶
TrieBucket[] count = new TrieBucket[words.length + 1];
for (String word : map.keySet()) {
int freq = map.get(word);
if (count[freq] == null) {
count[freq] = new TrieBucket();
}
add(count[freq], word);
}
for (int f = count.length - 1; res.size() < k && f > 0; f--) {
if (count[f] == null) continue;
get(count[f], res, k);
}
return res;
}
private void get(TrieBucket root, List<String> res, int k) {
if (root == null) return;
if (root.word != null) res.add(root.word);
if (res.size() == k) return;
for (int i = 0; i < 26; i++) {
if (root.next[i] != null) {
get(root.next[i], res, k);
}
}
}
private void add(TrieBucket root, String word) {
TrieBucket cur = root;
for (char ch : word.toCharArray()) {
if (cur.next[ch - 'a'] == null) {
cur.next[ch - 'a'] = new TrieBucket();
}
cur = cur.next[ch - 'a'];
}
cur.word = word;
}
class TrieBucket {
TrieBucket[] next;
String word;
public TrieBucket() {
this.next = new TrieBucket[26];
this.word = null;
}
}