LeetCode 347. Top K Frequent Elements

问题描述

  • 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 better than O(n log n), where n is the array’s size.
  • 地址

问题分析

  • 属于 Top K 问题范畴,类似于 LeetCode 215. Kth Largest Element in an Array ,只不过该题是求为出现次数的 Top K 所对应的元素。所以首先需要用 map 来统计次数。然后分为两种做法:
    • 。用一个大小为 K 的最小堆,来始终维护出现次数 Top K 的元素。堆里存的是一个对象。时间复杂度: O(NlogK)
      也有人用一个最大堆来维护出现次数 为 map.size() - k 小的元素,剩下的便是出现次数 Top K 的元素。
    • 桶排序,创建一个 list数组 bucket, bucket[i] 用来存储所有出现次数为i 的元素。然后再从后向前遍历 bucket数组,找到k个元素为止。

代码实现

    public List<Integer> topKFrequent(int[] nums, int k) {
        if(nums == null || k <= 0 || k > nums.length) {
            return new ArrayList<>();
        }

        HashMap<Integer, Integer> map = new HashMap<>();
        //统计次数
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
        }
        PriorityQueue<Node> minHeap = new PriorityQueue<>(new Comparator<Node>() {
            public int compare(Node o1, Node o2) {
                return o1.freq - o2.freq;
            }
        });
        for (Integer key : map.keySet()) {
            int freq = map.get(key);
            if (minHeap.size() == k && freq > minHeap.peek().freq) {
                minHeap.poll();
                minHeap.add(new Node(key, freq));
            }
            if (minHeap.size() < k) {
                minHeap.add(new Node(key, freq));
            }
        }
        ArrayList<Integer> res = new ArrayList<>();
        //将堆中元素加入res
        for (Node curNode : minHeap) {
            res.add(curNode.val);
        }
        Collections.reverse(res);
        return res;
    }
  • 桶排序
    public List<Integer> topKFrequent(int[] nums, int k) {
        if(nums == null || k <= 0 || k > nums.length) {
            return new ArrayList<>();
        }
        //统计次数
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
        }
        //桶排序
        List<Integer>[] bucket = new List[nums.length + 1];
        for (int key : map.keySet()) {
            int val = map.get(key);
            if (bucket[val] == null) {
                bucket[val] = new ArrayList<Integer>();
            }
            bucket[val].add(key);
        }
        List<Integer> res = new ArrayList<>();
        int count = 0;
        for (int i = bucket.length - 1; i >=0; i--) {
            if (bucket[i] == null) {
                continue;
            }
            for (int j = 0; j < bucket[i].size() && count < k; j++) {
                res.add(bucket[i].get(j));
                ++count;
            }
        }
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值