【Leetcode】23.合并K个排序链表(最小堆)

该博客介绍了如何使用最小堆解决LeetCode中的23题——合并K个排序链表。作者首先解释了最小堆的概念,并通过构建、插入和删除过程的图解辅助理解。解题步骤包括建立以链表头节点为节点的完全二叉树,形成最小堆,然后不断取出堆顶元素(即当前最小值)连接到结果链表,用链表的下一个节点替换并重新调整堆,直至所有链表元素都处理完毕。博客最后提供了2020年9月5日更新的优化代码,使用vector维护最小堆以减少时间和内存消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

点击打开题目

题目描述

在这里插入图片描述

题解

有多种方法,这个题我使用最小堆的方法。

首先了解一下最小堆的概念:最小堆 构建、插入、删除的过程图解

解题步骤

  1. 首先以各链表的头指针为结点构建一棵完全二叉树。
  2. 按最小堆的形式整理二叉树。
  3. 取二叉树的根结点,连在结果链表后。
  4. 用根结点所在链表的下一个结点作为根结点,并重新更新为最小堆。如果没有下一个结点了,则填入一个正无穷结点。
  5. 重复第3步,直到根结点为正无穷结点。

代码

2020.9.5更新:使用vector维护最小堆,节省了不少时间开销和内存开销。

/*
 * @lc app=leetcode.cn id=23 lang=cpp
 *
 * [23] 合并K个排序链表
 * 
 * 思路:最小堆,先构造一棵结点数为链表数的最小堆(完全二叉树)。
 * 依次取二叉树根结点插入结果链表,最小堆的根结点换成该结点的下一个元素,如果是NULL则换成正无穷。
 * 
 */

// @lc code=start
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

// 代码一:使用完全二叉树来构建,有额外的开销
/* class Solution { */
/* public: */
/*     struct Node  // 二叉树结点 */
/*     { */
/*         ListNode *node; */
/*         Node *left=nullptr, *right=nullptr; */
/*     }; */
/*     const int MAX_NUM = 9999999; */
/*     // 构建完全二叉树 */
/*     void build_tree(Node *&tree_root, const vector<ListNode*> &lists) */
/*     { */
/*         int pos = 0; */
/*         tree_root = new Node; */
/*         tree_root->node = lists[pos++]; */
/*         queue<Node*> Q; */
/*         Q.push(tree_root); */
/*         while(pos < lists.size()) */
/*         { */
/*             Node *node = Q.front(); */
/*             Q.pop(); */
/*             node->left = new Node; */
/*             node->left->node = lists[pos++]; */
/*             Q.push(node->left); */
/*             if (pos >= lists.size()) */
/*                 break; */

/*             node->right = new Node; */
/*             node->right->node = lists[pos++]; */
/*             Q.push(node->right); */
/*         } */
/*     } */
/*     // 销毁二叉树 */
/*     void destroy_tree(Node *node) */
/*     { */
/*         if (node == nullptr) */
/*             return; */
/*         destroy_tree(node->left); */
/*         destroy_tree(node->right); */
/*         delete node; */
/*     } */
/*     // 堆中元素下降 */
/*     void refresh_node(Node *now) */
/*     { */
/*         if (now->left != nullptr && now->right != nullptr) */
/*         { */
/*             Node *temp = now; */
/*             // 如果左右孩子都有,与其中小的比较 */
/*             // 右边小 */
/*             if (temp->left->node->val > temp->right->node->val) */
/*