📜  数据结构 |堆 |问题2(1)

📅  最后修改于: 2023-12-03 14:54:56.210000             🧑  作者: Mango

数据结构 | 堆 | 问题2

简介

堆(Heap)是一种特殊的树形数据结构,它满足以下两个条件:

  1. 堆中每个节点的值都必须不小于(或不大于)其子节点的值;
  2. 堆必须是一棵完全二叉树。

堆分为大根堆和小根堆。在大根堆中,每个节点的值都不小于其子节点的值;在小根堆中,每个节点的值都不大于其子节点的值。

堆可以用数组表示,堆顶元素即为数组第一个元素。将数组从1开始计数,则节点i的左子节点为2i,右子节点为2i+1,父节点为i/2。

问题描述

问题2:给定一个int数组arr和一个int x,找出arr中最大的x个数,按照由大到小的顺序输出。

例如,当arr=[1,3,2,5,4],x=3时,输出[5,4,3]。

解决方法

使用小根堆来维护最大的x个元素。首先将数组前x个元素插入堆中,然后遍历数组的剩余元素,如果元素比堆顶元素大,则将堆顶元素删除并将新元素插入堆中。

这样遍历完数组后,堆中剩下的x个元素即为最大的x个元素。

根据题目要求,需要将结果从大到小输出,因此可以使用List来保存堆中的元素,然后逆序输出List即可。另外,题目中未说明x的范围,如果x比较小,则可以使用优先队列(PriorityQueue)代替手写堆。

以下是Java实现:

import java.util.PriorityQueue;

public class TopK {
    public static void main(String[] args) {
        int[] arr = { 1, 3, 2, 5, 4 };
        int x = 3;
        int[] result = topK(arr, x);
        for (int num : result) {
            System.out.print(num + " ");
        }
        // output: 5 4 3
    }

    public static int[] topK(int[] arr, int x) {
        PriorityQueue<Integer> heap = new PriorityQueue<>(x);
        for (int i = 0; i < x; i++) {
            heap.offer(arr[i]);
        }
        for (int i = x; i < arr.length; i++) {
            if (arr[i] > heap.peek()) {
                heap.poll();
                heap.offer(arr[i]);
            }
        }
        int[] result = new int[x];
        int index = 0;
        while (!heap.isEmpty()) {
            result[index++] = heap.poll();
        }
        return result;
    }
}
总结

本文介绍了堆这种特殊的树形结构,并采用堆来解决问题2。堆在很多场景下都具有很好的效率,因此掌握堆的使用方法很有必要。