首页 > 其他分享 >力扣题目解析--合并k个升序链表

力扣题目解析--合并k个升序链表

时间:2024-11-20 10:19:12浏览次数:3  
标签:pq ListNode -- top next 链表 队列 升序

题目

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2:

输入:lists = []
输出:[]

示例 3:

输入:lists = [[]]
输出:[]

提示:

  • k == lists.length
  • 0 <= k <= 10^4
  • 0 <= lists[i].length <= 500
  • -10^4 <= lists[i][j] <= 10^4
  • lists[i] 按 升序 排列
  • lists[i].length 的总和不超过 10^4

代码展示 

#include <queue>
using namespace std;

struct Compare {
    bool operator()(ListNode* a, ListNode* b) {
        return a->val > b->val; // 最小堆
    }
};

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        priority_queue<ListNode*, vector<ListNode*>, Compare> pq;
        
        
        for (auto& list : lists) {
            if (list) {
                pq.push(list);
            }
        }
        
        ListNode* dummy = new ListNode(0);
        ListNode* current = dummy;
        
        while (!pq.empty()) {
            ListNode* top = pq.top();
            pq.pop();
            
            current->next = top;
            current = current->next;
            
            if (top->next) {
                pq.push(top->next);
            }
        }
        
        return dummy->next;
    }
};

写者心得 

练习中曾经做过合并两个链表的题,然后写者准备加一个循环,就是把他给的这个数组里面的链表提取出来之后再合并起来,但是运行出了bug,于是我就去找到了这样一个和我当初思路截然不同的做法,这个利用的是栈,代码比我当初利用for循环来进行链表合并要少很多

逐行解析

  1. 自定义比较器

    struct Compare {
        bool operator()(ListNode* a, ListNode* b) {
            return a->val > b->val; // 最小堆
        }
    };
    • 这是一个自定义的比较器,用于优先队列中的排序。
    • operator() 定义了比较规则,使得优先队列成为一个最小堆,即队列顶部的节点值是最小的。
  2. 创建优先队列

    priority_queue<ListNode*, vector<ListNode*>, Compare> pq;
    • 使用 priority_queue 创建一个最小堆,存储类型为 ListNode*
    • vector<ListNode*> 是优先队列的底层容器。
    • Compare 是自定义的比较器,确保优先队列按节点值从小到大排序。
  3. 初始化优先队列

    for (auto& list : lists) {
        if (list) { // 检查链表是否为空
            pq.push(list);
        }
    }
    • 遍历输入的链表列表 lists
    • 对于每个链表,检查其是否为空(if (list)),如果不为空,则将其头节点加入优先队列。
  4. 创建虚拟头节点

    ListNode* dummy = new ListNode(0);
    ListNode* current = dummy;
    • 创建一个虚拟头节点 dummy,值为 0。
    • current 指向 dummy,用于构建新的链表。
  5. 合并链表

    while (!pq.empty()) {
        ListNode* top = pq.top();
        pq.pop();
        
        current->next = top;
        current = current->next;
        
        if (top->next) {
            pq.push(top->next);
        }
    }
    • 当优先队列不为空时,进入循环。
    • 从优先队列中取出当前最小的节点 top
    • 将 top 添加到新链表中,即 current->next = top,并移动 current 到 top
    • 如果 top 有下一个节点(if (top->next)),则将 top->next 加入优先队列。
  6. 返回新链表的头节点

    return dummy->next;
    • 返回新链表的头节点,即 dummy 的下一个节点。

条件的使用

  • if (list):检查链表是否为空。只有非空链表的头节点才会被加入优先队列。
  • if (top->next):检查当前节点是否有下一个节点。如果有,则将下一个节点加入优先队列,以继续参与后续的合并操作。

 

1. 自定义比较器

什么是比较器?

比较器是一个函数对象,用于定义两个对象之间的比较规则。在 C++ 标准库中,许多容器(如 std::sortstd::priority_queue)都允许用户自定义比较器。

自定义比较器的例子
struct Compare {
    bool operator()(ListNode* a, ListNode* b) {
        return a->val > b->val; // 最小堆
    }
};
  • struct Compare:定义一个结构体 Compare,用于存储比较逻辑。
  • bool operator()(ListNode* a, ListNode* b):重载 () 操作符,使其像一个函数一样调用。
    • 参数 a 和 b 是两个 ListNode* 类型的指针。
    • 返回值 bool 表示 a 是否大于 b
    • return a->val > b->val;:如果 a 的值大于 b 的值,返回 true,否则返回 false。这使得优先队列成为一个最小堆。

2. 创建优先队列

什么是优先队列?

优先队列是一种特殊的队列,取出元素的顺序并不是按照进入的顺序,而是根据元素的优先级。在 C++ 中,std::priority_queue 是一个容器适配器,默认情况下是一个最大堆(即队列顶部的元素是最大的)。

创建最小堆的优先队列
priority_queue<ListNode*, vector<ListNode*>, Compare> pq;
  • priority_queue<ListNode*, vector<ListNode*>, Compare>
    • 第一个模板参数 ListNode*:优先队列中存储的元素类型。
    • 第二个模板参数 vector<ListNode*>:底层容器,用于存储元素。默认情况下是 vector
    • 第三个模板参数 Compare:自定义的比较器,用于定义元素的优先级

 

标签:pq,ListNode,--,top,next,链表,队列,升序
From: https://blog.csdn.net/wxtg1921/article/details/143868162

相关文章

  • Mit6.S081笔记Lab11: Network 网络设备驱动
    课程地址:https://pdos.csail.mit.edu/6.S081/2020/schedule.htmlLab地址:https://pdos.csail.mit.edu/6.S081/2020/labs/net.html我的代码地址:https://github.com/Amroning/MIT6.S081/tree/netxv6手册:https://pdos.csail.mit.edu/6.S081/2020/xv6/book-riscv-rev1.pdf相关翻译......
  • 超详细的Stable Diffusion(SD)本地部署教程,小白一看就会!
    一、StableDiffusion是什么?简单来讲,StableDiffusion(简称SD)是一款AI自动生成图片的软件。我们输入文字,SD就能生成相应的图片,不再像过去那样需要把图片“画”出来或者“拍”出来。有人说,我在学习一个软件之前是不是得先了解它的原理呢?我的回答是:不需要!很多人想学......
  • Linux基础命令二
    二、进阶命令2.1ps命令作用:监测进程。psaux:显示所有用户的进程可以看见CPU使用率,内存使用率、进程状态ps-ef系统上运行的所有进程可以看见PPID一些信息UID:启动这些进程的用户。PID:进程的进程ID。PPID:父进程的进程号(如果该进程是由另一个进程启动的)。C:进程生......
  • ISIS 中间系统到中间系统(Intermediate System to Intermediate System) 路由器到路由
    1.ISIS应用场景和技术特点用在运营商扩展性强,IP协议统一天下,ISIS可以支持各种协议,对ipx,ipv4,ipv6等等不同的网络协议,通过TLV方式扩咱扩展,TLV(Type-Length-Value)是一种数据结构,用于在IS-IS的协议数据单元(PDU)中传递额外的信息。TLV由三个部分组成:类型(Type)、长度(Length)和值(Valu......
  • php购物商城php毕业设计在线购物商城电商网站电子产品网站手机购物商城电子产品购物商
    一、功能介绍php在线购物商城电商网站详细技术:HTML+CSS+JS+PHP+MYSQL系统分为用户和管理员两种身份用户功能如下:1.登陆注册2.查看商品详情、蛋糕资讯3.加入购物车、结算订单4.评价5.修改密码6.搜索蛋糕7.退出登录管理员功能如下:1.登录退出2.蛋糕管理(添加、修改和......
  • 什么是OA办公系统?为什么OA办公系统对于企业的作用越来越重要?
    如何提升工作效率、优化资源配置、加强团队协作能力,成为了每个企业管理者亟需解决的关键问题。随着企业规模的扩展和业务流程的复杂化,传统的手工操作和纸质文件已经无法满足高效办公的需求。OA(OfficeAutomation)办公系统应运而生,成为了现代企业提高工作效率、优化管理流程、实现......
  • 【拥抱AI】大模型文本质量的高级评估方法详解
    在文本生成任务中,高级评估方法旨在更深入地评估生成文本的质量,不仅仅是基于表面的相似度指标,而是从语义、语法、情感等多个维度进行全面评估。以下是一些常用的高级评估方法及其详细讲解。1.语义相似度评估1.1BERT和Sentence-BERT背景:BERT(BidirectionalEncoderRepr......
  • 掌握Java“时空”,工作中关于时间类的使用
    掌握Java“时空”,工作中关于时间类的使用一、Date类概述java.util.Date类表示特定的瞬间,精确到毫秒。Date类的构造函数可以把毫秒值转成日期对象构造方法publicDate()//以当前时间创建时间对象publicDate(longdate)//分配Date对象并初始化此对象,以表示自从标准基......
  • 《数据库应用系统实践》------ 酒吧管理系统
    系列文章《数据库应用系统实践》------酒吧管理系统文章目录系列文章一、需求分析1、系统背景2、系统功能结构(需包含功能结构框图和模块说明)3.系统功能简介二、概念模型设计1.基本要素(符号介绍说明)2.ER图三、逻辑模型设计1.ER模型向关系模型转换规则2.转换后的关系模型......
  • Linux基本命令(三) 文本处理及优化终端操作
    目录一、文本处理  1.1内容匹配1.1.1grep文件内容搜索1.1.2 awk正则匹配内容1.2 内容打印 1.2.1head显示文件头部内容1.2.2tail显示文件底部内容1.2.3sed文件内容显示1.2.4cut列提取1.3 内容处理1.3.1内容替换1.3.2sort内容排序1.3.3uniq内容去重......