package com.lt.datastructure.MaxHeap; import java.util.LinkedList; import java.util.List; import java.util.TreeMap; import com.lt.datastructure.Queue.PriorityQueue; /** LeetCode347 给定一个非空的整数数组,返回其中出现频率前 k 高的元素。 示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 说明: 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。 频次: 用map 复杂度优于O(nlogn):优先队列 频次越低,优先于越高 1 TreeMap存储,键存数组的值,值存数组的值频次 2 新建Freq类,成员属性是e,freq,实现Comparable,重写CompareTo,相反地,频次小的优先级高,返回1 3 优先队列存储Freq,遍历map,如果没存满k个,继续入队,如果存满了,将队首元素和新元素的频次比较,优先级高的(频次低)出队 4 用LinkedList存储优先队列中的元素,作为结果输出 */ public class Solution{ private class Freq implements Comparable<Freq>{ public int e,freq; public Freq(int e, int freq) { this.e = e; this.freq = freq; } @Override public int compareTo(Freq another) { if(this.freq < another.freq){ return 1; }else if(this.freq > another.freq){ return -1; }else{ return 0; } } } public List<Integer> 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); } } //优先队列存储前k个频次最高的元素 PriorityQueue<Freq> pq = new PriorityQueue<>(); for(int key : map.keySet()){ //没存满,继续存 if(pq.getSize()<k){ pq.enqueue(new Freq(key,map.get(key))); //存满了,比较次数,次数低的优先级高,出队,频次高的入队 }else if(map.get(key)>pq.getFront().freq){ pq.dequeue(); pq.enqueue(new Freq(key,map.get(key))); } } //将优先队列的元素存于链表并作为结果输出 LinkedList<Integer> res = new LinkedList<>(); while(!pq.isEmpty()){ res.add(pq.dequeue().e); } return res; } }