📌  相关文章
📜  使用最小堆合并 K 个已排序链表的Java程序 – 第 2 组(1)

📅  最后修改于: 2023-12-03 15:06:57             🧑  作者: Mango

使用最小堆合并 K 个已排序链表的Java程序 – 第 2 组

简介

本文介绍如何使用最小堆(MinHeap)数据结构来合并 K 个已排序链表。合并 K 个已排序链表是 LeetCode 上的一道经典问题,其可以通过多种方法解决,包括分治法(Divide and Conquer)、归并排序(Merge Sort)和最小堆(MinHeap)等等。本文着重介绍如何使用最小堆(MinHeap)来解决这个问题。

最小堆(MinHeap)简介

最小堆(MinHeap)是一个二叉树,其满足以下两个条件:

  1. 它是一颗完全二叉树;
  2. 任意节点的值都小于或等于其子节点的值。

在最小堆中,根节点的值最小,因此也被称为最小值。除此之外,其他节点的顺序不做限制。

最小堆通常用数组来存储,数组下标从0开始,每个节点的索引为i,其左子节点的索引为2i+1,右子节点的索引为2i+2。

算法思路

我们可以使用最小堆来合并K个已排序链表。算法的基本思路如下所示:

  1. 创建一个大小为K的最小堆(MinHeap);
  2. 将K个链表的第一个节点加入到最小堆中;
  3. 从最小堆中取出最小的节点(值最小的节点);
  4. 将最小节点所在的链表的下一个节点加入到最小堆中;
  5. 重复步骤3和步骤4,直到所有节点都被加入到最小堆中;
  6. 最后,依次取出最小堆中的节点,将它们加入到结果链表中,即得到合并后的链表。
代码实现

下面是使用Java语言实现的合并K个已排序链表的代码。我们使用一个ListNode类来表示链表节点,使用一个MinHeap类来实现最小堆。

import java.util.PriorityQueue;

class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

class MinHeapNode implements Comparable<MinHeapNode> {
    ListNode node;

    public MinHeapNode(ListNode node) {
        this.node = node;
    }

    @Override
    public int compareTo(MinHeapNode o) {
        return node.val - o.node.val;
    }
}

class MinHeap {
    PriorityQueue<MinHeapNode> heap;

    public MinHeap() {
        heap = new PriorityQueue<>();
    }

    public void push(ListNode node) {
        heap.add(new MinHeapNode(node));
    }

    public ListNode pop() {
        return heap.poll().node;
    }

    public boolean isEmpty() {
        return heap.isEmpty();
    }
}

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        MinHeap heap = new MinHeap();
        for (ListNode node : lists) {
            if (node != null) {
                heap.push(node);
            }
        }

        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;

        while (!heap.isEmpty()) {
            ListNode node = heap.pop();
            tail.next = node;
            tail = tail.next;
            if (node.next != null) {
                heap.push(node.next);
            }
        }

        return dummy.next;
    }
}
总结

使用最小堆合并K个已排序链表是一种高效的算法。算法的时间复杂度为O(NlogK),其中N为所有链表中节点的个数,K为链表的个数。需要注意的是,在实现最小堆时,要使用 PriorityQueue 类来实现,而不能手动维护最小堆。