第347题:前K个高频元素

解题思路

347. 前 K 个高频元素
大体思路:
①先要计算出各数字所出现的频次。数字:频次。可见这是一个键值对形式,所以可以用双列集合Map来存储。
② 找到频次前K高个数值
对于②的实现有很多方法,下面给出了三种解法。

  • 使用数组进行全排序
  • 使用优先级队列进行排序
  • 使用桶排序

代码

方法一:全排序
//运行时间:17 ms  内存消耗:41.2MB
import java.util.Map.Entry;
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        //利用Map存储每个整数出现的次数
         Map<Integer , Integer> counts = new HashMap<>();
         for(int num : nums){
             counts.put(num,counts.getOrDefault(num,0)+1);
         }
         //Entry是Map中的  键值对 对象
         Entry<Integer , Integer>[] entries = new Entry[counts.size()];
         Set entry_set = counts.entrySet();
         entry_set.toArray(entries);    //把set转换为数组
         Arrays.sort(    //对数组按出现频度进行从大到小的排序
             entries,
             (Entry<Integer , Integer> e1 , Entry<Integer , Integer> e2) -> e2.getValue()-e1.getValue()
             );
         int[] result = new int[k];
         for(int i=0 ; i<k ; i++){
             result[i] = entries[i].getKey();
         }
         return result;
    }
}
方法二:使用优先级队列:PriorityQueue
//运行时间:15 ms  内存消耗:41 MB
import java.util.Map.Entry;
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        //利用Map存储每个整数出现的次数
         Map<Integer , Integer> counts = new HashMap<>();
         for(int num : nums){
             counts.put(num,counts.getOrDefault(num,0)+1);
         }
         //Entry是Map中的  键值对 对象
         Set<Entry<Integer , Integer>> entry_set = counts.entrySet();//泛型可加也可不加
         PriorityQueue<Entry<Integer , Integer>> queue = new PriorityQueue<>(
             (Entry<Integer , Integer> e1 , Entry<Integer , Integer> e2) -> e1.getValue()-e2.getValue()
         );
         for(Entry<Integer , Integer> entry : entry_set){
             if(queue.size()<k){
                 queue.offer(entry);
             }else if(entry.getValue()>queue.peek().getValue()){  //peek():取出堆顶元素
                 queue.poll();
                 queue.offer(entry);
             }
         }
         int[] result = new int[k];
         while(!queue.isEmpty()){
             result[--k] = queue.poll().getKey();
         }
         return result;
    }
}
方法三:桶排序
//运行时间:13ms  内存消耗:41.2MB
import java.util.Map.Entry;
//方法二:使用桶排序
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        //利用Map存储每个整数出现的次数
         Map<Integer , Integer> counts = new HashMap<>();
         for(int num : nums){
             counts.put(num,counts.getOrDefault(num,0)+1);
         }
         //Entry是Map中的  键值对 对象
         Set<Entry<Integer , Integer>> entry_set = counts.entrySet();//泛型可加也可不加

         //创建一个nums.length长度的集合,里面存放所有的桶,出现频次为n的数值放到[n-1]号桶里
         List<Integer>[] buckets = new List[nums.length ];
         int maxBucket = 0; //记录最大频次所在的桶的位置
         for(Entry<Integer , Integer> entry : entry_set){
             int frequency = entry.getValue();
             List<Integer> bucket = buckets[frequency-1];
             if(bucket == null){
                 bucket = new LinkedList<>();
                 buckets[frequency-1] = bucket;
                 maxBucket = Math.max(maxBucket , frequency-1);
             }
             bucket.add(entry.getKey());
         }
         int[] result = new int[k];
         int j=0;
         for(int i=maxBucket ; i>=0&&j<k; i--){  //从后往前遍历,拿了k个值就终止
            if(buckets[i] == null) continue;
            for(Integer number : buckets[i]){
                result[j++] = number;
            }  
         }
         return result;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值