剑指 Offer II 060. 出现频率最高的 k 个数字(347. 前 K 个高频元素)

题目:

思路:

【1】其实我觉得吧,这个题有点问题,说是必须优于O(n log n),那么是不是就是禁止使用堆了呢,优先队列里面使用的不就是堆排序的思想?那么时间复杂度也为O(n log n),这不就是禁止使用了。神神叨叨不干人事

代码展示:

//时间12 ms击败89.10%
//内存44.3 MB击败12.22%
//时间复杂度:O(Nlog⁡k),其中 N 为数组的长度。
//首先遍历原数组,并使用哈希表记录出现次数,每个元素需要 O(1) 的时间,共需 O(N) 的时间。
//随后,我们遍历「出现次数数组」,由于堆的大小至多为 k,因此每次堆操作需要 O(log⁡k) 的时间,共需 O(Nlog⁡k) 的时间。
//二者之和为 O(Nlog⁡k)。
//空间复杂度:O(N)。哈希表的大小为 O(N),而堆的大小为 O(k),共计为 O(N)。
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
        for (int num : nums) {
            occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
        }

        // int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
        PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
            public int compare(int[] m, int[] n) {
                return m[1] - n[1];
            }
        });
        for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
            int num = entry.getKey(), count = entry.getValue();
            if (queue.size() == k) {
                if (queue.peek()[1] < count) {
                    queue.poll();
                    queue.offer(new int[]{num, count});
                }
            } else {
                queue.offer(new int[]{num, count});
            }
        }
        int[] ret = new int[k];
        for (int i = 0; i < k; ++i) {
            ret[i] = queue.poll()[0];
        }
        return ret;
    }
}


//优化版本
//时间4 ms击败99.68%
//内存43.9 MB击败64.7%
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        int max = Integer.MIN_VALUE,min = Integer.MAX_VALUE;
        for (int num : nums) {
            max = Math.max(max,num);
            min = Math.min(min,num);
        }
        //这里虽说是可能会出现new 一个Integer.MAX_VALUE大小的数组,但是操作上会比使用hashMap要快
        int[] res = new int[max - min + 1];
        for (int num : nums)
            res[num - min]++;
        Queue<int[]> queue = new PriorityQueue<>((a,b)->(b[1] - a[1]));
        for (int i = 0; i < res.length; i++) {
            queue.add(new int[]{i + min,res[i]});
        }
        int[] ans = new int[k];
        for (int i = 0; i < k; i++) {
            ans[i] = queue.poll()[0];
        }
        return ans;
    }
}

 

posted @ 2023-03-23 12:10  忧愁的chafry  阅读(18)  评论(0编辑  收藏  举报