LeetCode刷题记录--前K个高频元素

前K个高频元素

    • 解法一:粗暴排序法
      • 复杂度分析
    • 解法二:最小堆

ps:要求 算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。

解法一:粗暴排序法

最简单粗暴的思路就是 使用排序算法对元素按照频率由高到低进行排序,然后再取前 kk 个元素。

以下十种排序算法,任你挑选!

LeetCode刷题记录--前K个高频元素_第1张图片
可以发现,使用常规的诸如 冒泡、选择、甚至快速排序都是不满足题目要求,它们的时间复杂度都是大于或者等于 O(n log⁡n)O(nlog⁡n),而题目要求算法的时间复杂度必须优于 O(n log n)O(nlogn)。

复杂度分析

时间复杂度:O(nlogn)O(nlogn),nn 表示数组长度。首先,遍历一遍数组统计元素的频率,这一系列操作的时间复杂度是 O(n)O(n);接着,排序算法时间复杂度为 O(nlogn)O(nlogn);因此整体时间复杂度为 O(nlogn)O(nlogn)。
空间复杂度:O(n)O(n),最极端的情况下(每个元素都不同),用于存储元素及其频率的 Map 需要存储 nn 个键值对。

解法二:最小堆

题目最终需要返回的是前 kk 个频率最大的元素,可以想到借助堆这种数据结构,对于 kk 频率之后的元素不用再去处理,进一步优化时间复杂度。
LeetCode刷题记录--前K个高频元素_第2张图片
具体操作为:

借助 哈希表 来建立数字和其出现次数的映射,遍历一遍数组统计元素的频率
维护一个元素数目为 kk 的最小堆
每次都将新的元素与堆顶元素(堆中频率最小的元素)进行比较
如果新的元素的频率比堆顶端的元素大,则弹出堆顶端的元素,将新的元素添加进堆中
最终,堆中的 kk 个元素即为前 kk 个高频元素

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map map=new HashMap<>();
        for(int i:nums){
            map.put(i,map.getOrDefault(i,0)+1);
        }

        PriorityQueue heap=new PriorityQueue((n1,n2)->
            map.get(n1)-map.get(n2)
        );
        for(int j:map.keySet()){
            heap.add(j);
            if(heap.size()>k){
                heap.poll();
            }
        }

        int[] result=new int[k];
        for(int a=k-1;a>=0;a--){
            result[a]=heap.poll();
        }
        
        return result;
    }
}

你可能感兴趣的:(leetcode)