题目描述
/**
*
* 给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
* 示例 1:
* 输入: nums = [1,1,1,2,2,3], k = 2
* 输出: [1,2]
*
* 示例 2:
* 输入: nums = [1], k = 1
* 输出: [1]
* 提示:
* 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
* 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
* 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
* 你可以按任意顺序返回答案。
*/
方法一:将元素和频率封装为一个内部类
package com.study.MaxHeap.TopKFrequentElements347;
import java.util.PriorityQueue;
import java.util.TreeMap;
class Solution {
private static class Freq implements Comparable<Freq>{
private int value;
private int freq;
public Freq(int value, int freq) {
this.value = value;
this.freq = freq;
}
@Override
public int compareTo(Freq other) {
if (this.freq > other.freq)
return 1;
else if (this.freq < other.freq)
return -1;
else
return 0;
}
}
public static int[] topKFrequent(int[] nums, int k) {
TreeMap<Integer, Integer> map = new TreeMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i]))
map.put(nums[i], map.get(nums[i]) + 1);
else
map.put(nums[i], 1);
}
// 优先队列 中 存放的是
PriorityQueue<Freq> queue = new PriorityQueue<>();
for (int key : map.keySet()) {
if (queue.size() < k) {
queue.add(new Freq(key, map.get(key)));
} else if (map.get(key) > queue.peek().freq) {
queue.remove();
queue.add(new Freq(key, map.get(key)));
}
}
int[] res = new int[queue.size()];
for (int i = 0; i < res.length; i++) {
res[i] = queue.remove().value;
}
return res;
}
public static void main(String[] args) {
int[] test = {1,1,1,2,2,3};
int[] ret = topKFrequent(test, 2);
for (int i :ret)
System.out.print(i + ",");
}
}
方法二:直接在优先队列的构造函数中传入 比较规则,因为内部类可以访问 方法的final变量(map),并获取到map的 value
package com.study.MaxHeap.TopKFrequentElements347;
Solution {
//升级版本 取消了自定义的内部类 进行 比较大小
//直接在 PriorityQueue的构造函数中 传入 Comparator 写明 比较规则
public static int[] topKFrequent(int[] nums, int k) {
final TreeMap<Integer, Integer> map = new TreeMap<>(); //jdk1.8后final 可以不写 ,但需要 名义final,即 后面不可改变
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i]))
map.put(nums[i], map.get(nums[i]) + 1);
else
map.put(nums[i], 1);
}
//因为 匿名内部类 可以直接获取到 方法中的 final变量(map) 所以可以直接在优先队列PriorityQueue存放 key,但是比较map的value
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer a, Integer b) {
return map.get(a) - map.get(b);
}
});
for (int key : map.keySet()) {
if (queue.size() < k) {
queue.add(key);
} else if (map.get(key) > map.get(queue.peek())) {
queue.remove();
queue.add(key);
}
}
int[] res = new int[queue.size()];
for (int i = 0; i < res.length; i++) {
res[i] = queue.remove();
}
return res;
}
public static void main(String[] args) {
int[] test = {1,1,1,2,2,3};
int[] ret = topKFrequent(test, 2);
for (int i :ret)
System.out.print(i + ",");
}
}