leetcode 力扣 347 前K个高频元素

69 阅读1分钟

如果用堆排序的话,这题和 数组中的第k个最大元素 是一模一样的。无非是把结点元素换成键值对而已。

需要注意的是,要取出所有k个元素,所以要加等于号,i >= list.size() - k,与215题不同:

// 取出前 k 个元素
        for (int i = heapSize - 1, j = 0; i >= list.size() - k; i--, j++) {
            // 取堆顶元素
            res[j] = list.get(0).getKey();

            // 用最后一个叶子结点替补堆顶元素
            Collections.swap(list, 0, i);
            
            // 并调整大根堆
            maxHeapify(list, 0, --heapSize);
        }

完整代码:

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        // 使用哈希表统计每个数字出现的次数
        Map<Integer, Integer> map = new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        // 将 Set 转换为 List
        Set<Map.Entry<Integer, Integer>> entries = map.entrySet();

        List<Map.Entry<Integer, Integer>> list = new ArrayList<>(entries);

        // 对 list 建立大根堆
        int heapSize = list.size();
        buildMaxHeap(list, heapSize);

        int[] res = new int[k];

        // 取出前 k 个元素
        for (int i = heapSize - 1, j = 0; i >= list.size() - k; i--, j++) {
            // 取堆顶元素
            res[j] = list.get(0).getKey();

            // 用最后一个叶子结点替补堆顶元素
            Collections.swap(list, 0, i);
            
            // 并调整大根堆
            maxHeapify(list, 0, --heapSize);
        }

        return res;
    }

    public void buildMaxHeap(List<Map.Entry<Integer, Integer>> list, int heapSize) {
        // 从最后一个非叶子结点开始建堆
        for (int i = heapSize / 2 - 1; i >= 0; i--) {
            maxHeapify(list, i, heapSize);
        }
    }

    public void maxHeapify(List<Map.Entry<Integer, Integer>> list, int i, int heapSize) {
        // 准备好两个指针:结点 i 的左孩子和右孩子
        int left = i * 2 + 1;
        int right = i * 2 + 2;
        int largest = i;

        // 写好递归出口,并判断 i 和 left 谁更大
        if (left < heapSize && list.get(left).getValue() > list.get(i).getValue()) {
            largest = left;
        }

        // 写好递归出口,并判断 largest 和 right 谁更大
        if (right < heapSize && list.get(right).getValue() > list.get(largest).getValue()) {
            largest = right;
        }

        // 如果 largest 是 left 和 right 之一
        if (largest != i) {

            // 使用 Collections.swap() 交换
            Collections.swap(list, i, largest);

            // 调整 largest 的子结点
            maxHeapify(list, largest, heapSize);
        }
    }
}