解这类求"前k个"的题目,关键是看如何定义优先级以及优先队列中元素的数据结构。
题目中有”前k个“这样的字眼,应该很自然地联想到优先队列。
优先级别可以由字符串出现的次数来决定,出现的次数越多,优先级别越高,反之越低。
统计词频的最佳数据结构就是哈希表(Hash Map),利用一个哈希表,就能快速地知道每个单词出现的次数。
将单词和其出现的次数作为一个新的对象来构建一个优先队列,那么这个问题就很轻而易举地解决了。
import java.util.*;
/**
* @author MasterYee
* @Description:优先级队列+HashMap实现
* @date: 2020/4/2
*/
public class Solution {
public List<Integer> topKFrequent(int[] nums, int k) {
List<Integer> ret = new ArrayList<>();
// key为数字,value为key出现的次数
HashMap<Integer, Integer> keyCountMap = new HashMap<>();
// 定义一个优先级队列,将key保存进去
// 自定义优先级比较器,从map中取对应value(即出现次数)越大,优先级越高
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
if (keyCountMap.get(o1) < keyCountMap.get(o2)) return 1; // o1次数小,排后面
else if (keyCountMap.get(o1) > keyCountMap.get(o2)) return -1; // o1次数大 优先级高 排前面
else return 0;
}
});
// 遍历数组
for (int i = 0; i < nums.length; i++) {
if(keyCountMap.get(nums[i]) == null) {
keyCountMap.put(nums[i],1);
} else {
int count = keyCountMap.get(nums[i]);
count ++;
keyCountMap.put(nums[i],count);
}
}
// 遍历map 加入优先级队列
for (Map.Entry<Integer, Integer> entry :
keyCountMap.entrySet()) {
priorityQueue.add(entry.getKey());
}
// 拿出前k个放入list
for (int i = 0; i <k ; i++) {
ret.add(priorityQueue.poll());
}
return ret;
}
}