LeetCode——347. 前 K 个高频元素【最小堆实现】
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例2:
输入: nums = [1], k = 1
输出: [1]
1.思路
①题目中要求我们返回前K个高频的元素,那么我们可以使用最小堆【Java中自带的优先队列】,保证二叉树中每次保留的都是前K个最大的即可。
②对于数值及其出现的次数,我们可以采用Map的实现子类TreeMap。
③Java自带的优先队列所使用的泛型,我们可以封装为一个类,其中,类包含值和次数。
2.代码过程
2.1 将nums数组中的值与次数对应起来【TreeMap】
TreeMap<Integer,Integer> map = new TreeMap<>();
for(int num : nums){
if(map.containsKey(num)){
map.put(num, map.get(num) + 1);
}else{
map.put(num,1);
}
}
2.2 定义内部类Freq,将数值与次数封装为一个对象【Freq必须可比,重写compareTo】
class Freq implements Comparable<Freq> {
int num; //数字
int count;//数字出现的次数
public Freq(int num, int count){
this.num = num;
this.count = count;
}
@Override
public int compareTo(Freq o) {
return this.count - o.count;//当前 - 传入
}
}
2.3 使用Java自带的优先队列PriorityQueue<Freq>遍历map的键,保证队列中为前k个最大值
//Java自带的优先队列是最小堆构建的 值越小越往上走
PriorityQueue<Freq> queue = new PriorityQueue<>();
for(int num : map.keySet()){
if(queue.size() < k){
queue.offer(new Freq(num, map.get(num)));
}else if(map.get(num) > queue.peek().count){
queue.remove();
queue.add(new Freq(num, map.get(num)));
}
}
int[] temp = new int[k];
for (int i = 0; i < k; i++) {
temp[i] = queue.remove().num;
}
3.全部代码
import java.util.PriorityQueue;
import java.util.TreeMap;
public class Solution347 {
public int[] topKFrequent(int[] nums, int k) {
TreeMap<Integer,Integer> map = new TreeMap<>();
for(int num : nums){
if(map.containsKey(num)){
map.put(num, map.get(num) + 1);
}else{
map.put(num,1);
}
}
//Java自带的优先队列是最小堆构建的 值越小越往上走
PriorityQueue<Freq> queue = new PriorityQueue<>();
for(int num : map.keySet()){
if(queue.size() < k){
queue.offer(new Freq(num, map.get(num)));
}else if(map.get(num) > queue.peek().count){
queue.remove();
queue.add(new Freq(num, map.get(num)));
}
}
int[] temp = new int[k];
for (int i = 0; i < k; i++) {
temp[i] = queue.remove().num;
}
return temp;
}
class Freq implements Comparable<Freq> {
int num; //数字
int count;//数字出现的次数
public Freq(int num, int count){
this.num = num;
this.count = count;
}
@Override
public int compareTo(Freq o) {
return this.count - o.count;//当前 - 传入
}
}
}