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

时间: 2024-07-31 23:25:38

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

347 Top K Frequent Elements 前K个高频元素

给定一个非空的整数数组,返回其中出现频率前 k 高的元素.例如,给定数组 [1,1,1,2,2,3] , 和 k = 2,返回 [1,2].注意:    你可以假设给定的 k 总是合理的,1 ≤ k ≤ 数组中不相同的元素的个数.    你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小.详见:https://leetcode.com/problems/top-k-frequent-elements/description/C++: class Solution { pub

前K个高频元素

数据结构--堆 Heap是一种数据结构具有以下的特点: 1)完全二叉树: 2)heap中存储的值是偏序: Min-heap: 父节点的值小于或等于子节点的值: Max-heap: 父节点的值大于或等于子节点的值: 1.堆的存储: 一般都用数组来表示堆,i结点的父结点下标就为(i–1)/2.它的左右子结点下标分别为2 * i + 1和2 * i + 2.如第0个结点左右子结点下标分别为1和2 2.堆的操作:insert 插入一个元素:新元素被加入到heap的末尾,然后更新树以恢复堆的次序. 每次插

[LeetCode]347. 前 K 个高频元素(堆)

题目 给定一个非空的整数数组,返回其中出现频率前?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?是数组的大小. 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problem

[LeetCode] Top K Frequent Elements 前K个高频元素

Given a non-empty array of integers, return the k most frequent elements. For example,Given [1,1,1,2,2,3] and k = 2, return [1,2]. Note: You may assume k is always valid, 1 ≤ k ≤ number of unique elements.    Your algorithm's time complexity must be

从一个序列中获取前K大的数的一种方法

这个方法是利用快速排序的.在快速排序中,得到中间元素(pivot)之后,比较中间元素之前的元素个数和K的大小关系,从而确定后面该往哪个方向继续递归.如果中间元素前面的元素个数等于K,那就停止递归过程:如果中间元素前面元素个数小于K,那就再中间元素后面进行递归:否则就往中间元素前面进行递归.这样最终得到的是没有排序的前K大的元素,这样再对前K个元素进行一次真正的快速排序.这样就能得到排好序的前K大元素.我随机生成了一个100000个整型数据的文件进行测试,求前10000个元素.这样做用了0.984

关于leetcode第K个最大元素的几种解法

对于这一题我使用了最大堆,快速排序,归并排序几种解法来做这一题,速度最快的是归并排序 使用定值的最小堆每次更新数组最后剩下前k个最大元素,而且堆顶就是我们要的第K个元素. 堆排序: import heapq class Solution(object): def findKthLargest(self, nums, k): """ :type nums: List[int] :type k: int :rtype: int """ self.mi

若干个(大量)数字中找前K大/小的元素--数值型

方法一:根据快速排序划分的思想 : (1) 递归对所有数据分成[a,b)b(b,d]两个区间,(b,d]区间内的数都是大于[a,b)区间内的数 : (2) 对(b,d]重复(1)操作,直到最右边的区间个数小于100个. 注意[a,b)区间不用划分 :因为[a,b)区间一定小于(b,d]区间: (3) 返回上一个区间,并返回此区间的数字数目. 如果个数大于100,对(b,d]重复(1)操作,直到最右边的区间个数小于100个: 如果个数小于100,对上一区间的左边进行划分,分为[a2,b2)b2(b

算法导论学习之线性时间求第k小元素+堆思想求前k大元素

对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思路例如以下: 1.分解:将A[p,r]分解成A[p,q-1]和A[q+1,r]两部分.使得A[p,q-1]都小于A[q],A[q+1,r]都不小于A[q]; 2.求解:假设A[q]恰好是第k小元素直接返回,假设第k小元素落在前半区间就到A[p,q-1]递归查找.否则到A[q+1,r]中递归查找. 3

取前k个出现频率最大的单词

package aprioriproduct; import java.io.BufferedReader; import java.io.FileReader; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import ja