LeetCode347:返回频率前K高的元素,基于优先队列实现

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;        
      }
  }

 

转载于:https://www.cnblogs.com/ltfxy/p/10068314.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值