Leetcode【TopK】| 347. 前 K 个高频元素

题目

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
 输入: nums = [1,1,1,2,2,3], k = 2
 输出: [1,2]
示例 2:
 输入: nums = [1], k = 1
 输出: [1]
提示:
 1. 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
 2. 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。
 3. 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
 4. 你可以按任意顺序返回答案。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/top-k-frequent-elements

解题

哈希排序

自己首先的思路就是用一个哈希表存储每个元素以及它们在数组中出现的次数,然后将该哈希依照次数进行排序,然后再依次输出。(重点:哈希表中比较器排序的写法)

class Solution {
   
    public int[] topKFrequent(int[] nums, int k) {
   
        int[] res = new int[k];
        //建立一个按value排序的HashMap
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();//key保存 数组元素值,value保存该值出现次数
        for (int num : nums) {
   
            map.put(num, map.getOrDefault(num, 0) + 1);
        }
        //比较器 list将map中的每个<key,value>即为一个entry保存为一个list
        List<Map.Entry<Integer,Integer>> list = new ArrayList<Map.Entry<Integer,Integer>>(map.entrySet());
        Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>(){
   
            //降序排序
            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2){
   
                return o2.getValue().compareTo(o1.getValue());
            }
        });
        //输出map中前k个
        //写法1
        //int i = 0;
        //for(Map.Entry<Integer, Integer> mapping:list){
   
        //    if(i == k){
   
        //        break;
        //    }else{
   
        //        res[i] = mapping.getKey();
        //    }
        //    i++;   
        //}
        //写法2
        for(int i = 0 ; i < k; i++){
   
            res[i] = list.get(i).getKey();
        }
        return res;
    }
}

在这里插入图片描述

TopK问题解法

参考以及代码来源: 4 种方法秒杀 TopK(计数排序/快排变形/堆/二叉搜索树)
其实是几种比较优秀的排序算法的应用,对排序算法不了解可以先看这篇:十种排序算法详解&Java实现
TopK问题,不管是求前K大/前K小/第K大/第K小,都有以下四种不错的方法:

  1. O(N):用快排变形最最高效解决TopK问题
  2. O(NlogK):大根堆(前K小)/小根堆(前K大)
  3. O(NlogK):二叉搜索树
  4. O(N):对于数据范围有限的情况下,可以用计数排序O(N)高效解决。

其中的很多方法其实在求TopK问题时,是不需要对整个序列进行排序的,应用一些较快的排序思想,在排序过程中就可得到结果,而不需全部排序完毕。

快排变形

因为每次快排是选出一个数(一般从第一个数开始)经过一系列交换找到该数在整个序列中所在的位置,对整个序列进行一次切分,结果为该数左边为比该数小的元素,右边为比该数大的元素。所以在解决TopK问题时,如果这次快排选出的数正好是第K个元素,结果已经出来了;如果不是根据两者的大小关系,看下次切分从哪个范围内选择数值即下次切分右段还是左段。

class Solution {
   
    class<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值