题目
请找出数组中出现频率最高的k个数字。例如,当k等于2时,输入数组[1,2,2,1,3,1],由于数字1出现了3次,数字2出现了2次,数字3出现了1次,因此出现频率最高的2个数字是1和2。
分析
如果在面试过程中遇到这个题目,首先要想到的是解决这个题目需要用到哈希表。这个题目的输入是一个数组,哈希表可以用来统计数组中数字出现的频率,哈希表的键是数组中出现的数字,而值是数字出现的频率。
接下来找出出现频率最高的k个数字。可以用一个最小堆存储频率最高的k个数字,堆中的每个元素是数组中的数字及其在数组中出现的次数。由于比较的是数字的频率,因此设置最小堆比较元素的规则,以便让频率最低的数字位于堆的顶部。
解
public class Test {
public static void main(String[] args) {
int[] nums = {1, 2, 2, 1, 3, 1};
List<Integer> result = topKFrequent(nums, 2);
System.out.println(result);
}
public static List<Integer> topKFrequent(int[] nums, int k) {
Map<Integer, Integer> numToCount = new HashMap<>();
for (int num : nums) {
numToCount.put(num, numToCount.getOrDefault(num, 0) + 1);
}
Queue<Map.Entry<Integer, Integer>> minHeap = new PriorityQueue<>(
(e1, e2) -> e1.getValue() - e2.getValue()
);
for (Map.Entry<Integer, Integer> entry : numToCount.entrySet()) {
if (minHeap.size() < k) {
minHeap.offer(entry);
}
else {
if (entry.getValue() > minHeap.peek().getValue()) {
minHeap.poll();
minHeap.offer(entry);
}
}
}
List<Integer> result = new LinkedList<>();
for (Map.Entry<Integer, Integer> entry : minHeap) {
result.add(entry.getKey());
}
return result;
}
}