美文网首页
LeetCode 第347题:前 K 个高频元素

LeetCode 第347题:前 K 个高频元素

作者: 放开那个BUG | 来源:发表于2021-06-10 22:12 被阅读0次

    1、前言

    题目描述

    2、思路

    这道题不难,用 map 统计每个数字的 frequency 后,然后排序(nlogn)或者保持一个数量为 k 的小根堆(nlogk)就能解决。但是这不是终极解决方案,终极方案是使用桶排序。

    桶排序是将要排序的数字落在一个桶内,这样落在不同桶内的数字天然有序,就是比较费空间而已。以此题为例,我们定义一个 nums.length + 1 的桶(利用 frequency 作为索引,如果只有一个数,索引为1,那么空间为 nums.length + 1)。map 统计完每个数字的 frequency 后,然后将相应的数字放到索引里。因为有相同的 frequency 有多个数,所以需要一个 list 来包裹。遍历完后再统计一遍即可。

    3、代码

    public class Q347_TopKFrequent {
    
        class Num{
            private int value;
            private int frequency;
    
            public Num(int value, int frequency) {
                this.value = value;
                this.frequency = frequency;
            }
    
            @Override
            public boolean equals(Object obj) {
                return ((Num)obj).value == this.value;
            }
        }
    
        /**
         * 普通的小根堆解法
         * @param nums
         * @param k
         * @return
         */
        public int[] topKFrequent2(int[] nums, int k) {
            if(nums == null || nums.length == 0){
                return null;
            }
    
            Map<Integer, Num> map = new HashMap<>();
            for (int num : nums) {
                if(map.containsKey(num)){
                    Num n = map.get(num);
                    n.frequency++;
                    map.put(num, n);
                }else {
                    map.put(num, new Num(num, 1));
                }
            }
    
            PriorityQueue<Num> priorityQueue = new PriorityQueue<>(new Comparator<Num>() {
                @Override
                public int compare(Num o1, Num o2) {
                    return o1.frequency - o2.frequency;
                }
            });
    
            // nlogk,比 nlogn 没快多少
            for (Integer key : map.keySet()) {
                if(priorityQueue.size() < k){
                    priorityQueue.add(map.get(key));
                }else if(map.get(key).frequency > map.get(priorityQueue.peek().value).frequency){
                    priorityQueue.poll();
                    priorityQueue.add(map.get(key));
                }
            }
    
            int[] res = new int[k];
            for(int i = 0; i < res.length; i++){
                res[i] = priorityQueue.poll().value;
            }
    
            return res;
        }
    
        public int[] topKFrequent(int[] nums, int k) {
            if(nums == null || nums.length == 0){
                return null;
            }
    
            Map<Integer, Num> map = new HashMap<>();
            for (int num : nums) {
                if(map.containsKey(num)){
                    Num n = map.get(num);
                    n.frequency++;
                    map.put(num, n);
                }else {
                    map.put(num, new Num(num, 1));
                }
            }
    
            // 桶排序,将 frequency 作为数组 index,value 作为数组的值
            List<Integer>[] total = new ArrayList[nums.length + 1];
            for (Integer key : map.keySet()) {
                Num num = map.get(key);
                if(total[num.frequency] == null){
                    total[num.frequency] = new ArrayList<>();
                }
                total[num.frequency].add(num.value);
            }
    
            int[] res = new int[k];
            // 桶排序后,frequency 大的都在数组后面
            for(int i = 0, j = total.length - 1; i < k && j >= 0;j--){
                if(total[j] != null){
                    for (Integer num : total[j]) {
                        if(i >= k){
                            return res;
                        }
                        res[i++] = num;
                    }
                }
            }
    
            return res;
        }
    
        public static void main(String[] args) {
            int[] nums = {1, 2};
            int k = 2;
            int[] res = new Q347_TopKFrequent().topKFrequent(nums, k);
            for (int re : res) {
                System.out.println(re);
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:LeetCode 第347题:前 K 个高频元素

          本文链接:https://www.haomeiwen.com/subject/ovjreltx.html