LeetCode hard也就这么回事

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

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

示例 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

        老样子,先贴我的图,可以说是又快又好,不过这里原题给的是子链表有序(常规写法也能写,不难),如果子链表无序,那各位读者应该是焦头烂额+汗流浃背了

            这个题,其实看完我上一篇分享可以立马写出来了,链表排序?看完你也能手撕 
思路还是一样,先转换成数组存放,再排序,再存回链表中(思路很简单)
 

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        vector<int> s;  // 存储所有链表节点的值的容器

        // 遍历所有链表,将节点的值依次放入容器中
        for (int i = 0; i < lists.size(); i++) {
            ListNode* cur = lists[i]; // 当前链表的头节点
            while (cur != nullptr) {
                s.push_back(cur->val); // 将节点值加入容器
                cur = cur->next; // 指针移动到下一个节点
            }
        }
        
        sort(s.begin(),s.end()); // 将容器中的值进行排序(升序)
        
        ListNode *tt = new ListNode(-1); // 创建一个哑节点 tt,用于构建结果链表
        ListNode *res = tt; // 使用 res 保存结果链表的头节点
        int i = 0; // 用于遍历排序后的容器 s
        
        // 遍历列表
        for (int j = 0; j < lists.size(); j++) {       
            ListNode* cur1 = lists[j]; // 当前链表的头节点
            while(cur1 != nullptr) {
                cur1->val = s[i++]; // 将排序后的值赋给当前节点
                tt->next = cur1; // 连接当前节点到结果链表
                tt = cur1; // tt 指针移动到当前节点
                cur1 = cur1->next; // cur1 指针移动到下一个节点
            }
        }
        
        return res->next; // 返回结果链表的头节点
    }
};

以下是LeetCode官方的各种题解,为大家添加上了注释

方法一:顺序合并

我们可以想到一种最朴素的方法:用一个变量 ans 来维护以及合并的链表,第 i次循环把第 i 个链表和 ans 合并,答案保存到 ans 中。

class Solution {
public:
    // 合并两个有序链表
    ListNode* mergeTwoLists(ListNode* a, ListNode* b) {
        // 如果其中一个链表为空,则直接返回另一个链表
        if ((!a) || (!b)) return a ? a : b;
        
        ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
        while (aPtr && bPtr) {
            if (aPtr->val < bPtr->val) {
                // 当a链表的值小于b链表的值时,将a链表的节点拼接到结果链表后面,并更新a链表的指针
                tail->next = aPtr; aPtr = aPtr->next;
            } else {
                // 当a链表的值大于等于b链表的值时,将b链表的节点拼接到结果链表后面,并更新b链表的指针
                tail->next = bPtr; bPtr = bPtr->next;
            }
            // 更新结果链表的尾指针
            tail = tail->next;
        }
        // 将剩下的未合并的链表直接拼接到结果链表的尾部
        tail->next = (aPtr ? aPtr : bPtr);
        
        // 返回结果链表
        return head.next;
    }

    // 合并K个有序链表
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode *ans = nullptr;
        for (size_t i = 0; i < lists.size(); ++i) {
            // 逐个合并链表,将结果保存到ans中
            ans = mergeTwoLists(ans, lists[i]);
        }
        // 返回最终的合并结果
        return ans;
    }
};


方法二:分治合并

考虑优化方法一,用分治的方法进行合并。

class Solution {
public:
    // 合并两个有序链表
    ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
        if ((!a) || (!b)) return a ? a : b; // 如果其中一个链表为空,则直接返回另一个链表
        ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
        while (aPtr && bPtr) {
            if (aPtr->val < bPtr->val) { // 比较两个节点的值,将较小的节点接入结果链表
                tail->next = aPtr; 
                aPtr = aPtr->next; // 更新a链表指针
            } else {
                tail->next = bPtr; 
                bPtr = bPtr->next; // 更新b链表指针
            }
            tail = tail->next; // 更新结果链表的尾节点
        }
        tail->next = (aPtr ? aPtr : bPtr); // 将剩余未合并完成的节点接入结果链表
        return head.next; // 返回结果链表的头节点
    }

    // 递归合并多个有序链表
    ListNode* merge(vector <ListNode*> &lists, int l, int r) {
        if (l == r) return lists[l]; // 当l和r相等时,表示只有一个链表,直接返回该链表
        if (l > r) return nullptr; // 当l大于r时,表示没有待合并的链表,返回空指针
        int mid = (l + r) >> 1; // 计算中间位置
        return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r)); // 递归合并左右两个部分
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        return merge(lists, 0, lists.size() - 1); // 调用递归函数,合并整个链表数组
    }
};


方法三:使用优先队列合并

这个方法和前两种方法的思路有所不同,我们需要维护当前每个链表没有被合并的元素的最前面一个,k 个链表就最多有 k 个满足这样条件的元素,每次在这些元素里面选取 val 属性最小的元素合并到答案中。在选取最小元素的时候,我们可以用优先队列来优化这个过程。
 

class Solution {
public:
    // 定义结构体Status,用于在优先队列中存储节点信息
    struct Status {
        int val; // 节点的值
        ListNode *ptr; // 节点指针
        bool operator < (const Status &rhs) const {
            return val > rhs.val; // 优先队列按照节点值的大小进行排序
        }
    };

    priority_queue<Status> q; // 创建优先队列q,按照节点值的大小进行排序

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        // 将每个链表的第一个节点放入优先队列
        for (auto node : lists) {
            if (node)
                q.push({node->val, node});
        }

        ListNode head, *tail = &head; // 创建结果链表的头节点head和尾节点tail
        while (!q.empty()) {
            auto f = q.top();
            q.pop();
            tail->next = f.ptr; // 将当前队列中最小的节点连接到结果链表的尾部
            tail = tail->next; // 更新尾节点为当前节点

            if (f.ptr->next)
                q.push({f.ptr->next->val, f.ptr->next}); // 如果当前节点还有下一个节点,则将下一个节点放入优先队列继续排序
        }

        return head.next; // 返回结果链表的头节点
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/472196.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Day72:WEB攻防-业务逻辑篇水平越权垂直越权未授权访问检测插件SRC项目

目录 逻辑越权-检测原理-水平&垂直&未授权 水平越权&#xff1a;同级别的用户之间权限的跨越 垂直越权&#xff1a;低级别用户到高级别用户权限的跨越 未授权访问&#xff1a;无登录用户就能直接访问到需验证应用 逻辑越权-检测项目-BURP插件&对比项目 Xia_Y…

【开源鸿蒙】编译OpenHarmony轻量系统QEMU RISC-V版

文章目录 一、背景介绍二、准备OpenHarmony源代码三、准备hb命令3.1 安装hb命令3.2 检查hb命令 四、编译RISC-V架构的OpenHarmony轻量系统4.1 设置hb构建目标4.2 启动hb构建过程 五、问题解决5.1 hb set 报错问题解决 六、参考链接 开源鸿蒙坚果派&#xff0c;学习鸿蒙一起来&a…

【操作系统】以Pthread线程库为例详解多线程并发运行的特点

目录 写在开头 1.线程的创建 2.主线程与子线程的结束顺序 3.线程之间的数据共享与并发执行 4.蒙特卡洛法求pi&#xff08;单线程&#xff09; 5.蒙特卡洛法求pi&#xff08;多线程&#xff09; 写在最后 写在开头 近期准备重学操作系统&#xff0c;感觉还是有很多细节的…

通过切面编程(AOP)实现不同字段转换为同一字段

文章目录 前言一、切面编程(AOP)是什么&#xff1f;二、demo样例1.实体类a.新增订单b.更新订单b.日志实体类 2.实现相关a.类型转换接口类b.类型转换接口实现类c.自定义注解d.切面配置e.运行 三、结果示例四、其他 前言 项目中有很多场景需要去记日志&#xff0c;&#xff0c;也…

深入浅出前端本地储存

引言 2021 年&#xff0c;如果你的前端应用&#xff0c;需要在浏览器上保存数据&#xff0c;有三个主流方案&#xff1a; CookieWeb Storage (LocalStorage)IndexedDB 这些方案就是如今应用最广、浏览器兼容性最高的三种前端储存方案 今天这篇文章就聊一聊这三种方案的历史…

Python学习:列表

Python 列表概念 在Python中&#xff0c;列表&#xff08;List&#xff09;是一种有序、可变、允许重复元素的数据结构。列表使用方括号 ​[]​来表示&#xff0c;可以包含任意类型的元素&#xff0c;如整数、字符串、列表等。 Python 访问列表中的值 在Python中&#xff0…

BI(商业智能):开启数据驱动的未来

在当今信息时代&#xff0c;企业和组织面临着大量的数据和信息。这些数据包含了各种各样的信息&#xff0c;从市场趋势和消费者行为到销售数据和供应链信息。对于企业而言&#xff0c;利用这些数据来做出明智的决策&#xff0c;提高效率和竞争力变得尤为重要。而商业智能&#…

Learn OpenGL 22 高级光照与Gamma校正

高级光照 Blinn-Phong 冯氏光照不仅对真实光照有很好的近似&#xff0c;而且性能也很高。但是它的镜面反射会在一些情况下出现问题&#xff0c;特别是物体反光度很低时&#xff0c;会导致大片&#xff08;粗糙的&#xff09;高光区域。下面这张图展示了当反光度为1.0时地板会…

JS+CSS3点击粒子烟花动画js特效

JSCSS3点击粒子烟花动画js特效 JSCSS3点击粒子烟花动画js特效

docker harbor.v2.9.2搭建镜像无法下载问题解决

在通过部署docker harbor时&#xff0c;采用的是离线包的方式&#xff0c;当解压压缩包后&#xff0c;执行prepare脚本步骤中有一步是要获取prepare:v2.9.2版本镜像 结果执行脚本时报如下错误&#xff1a; Unable to find image goharbor/prepare:v2.9.2 locally 这时候我们就…

若依ruoyi-vue中的文件上传和下载

文章目录 文件上传后端实现前端实现 文件下载后端实现前端实现 在若依&#xff08;Ruoyi&#xff09;框架中&#xff0c;结合 Vue 前端框架&#xff0c;文件的上传和下载通常使用以下方法实现&#xff1a; 文件上传 若依现成的功能里面没有文件上传&#xff0c;但是集成了文件…

探索智慧农业项目方案,开启农业智能化新篇章

1. 背景 随着科技的飞速发展和全球人口的不断增长&#xff0c;传统农业模式已难以满足日益增长的粮食和农产品需求。同时&#xff0c;气候变化、资源短缺等环境问题也对农业生产带来了巨大挑战。因此&#xff0c;智慧农业作为一种集成了现代信息技术和农业生产的创新模式&#…

位图与布隆过滤器

目录 一、位图 1、问题用位图来解决&#xff1a; 二、 布隆过滤器 1、将哈希与位图结合&#xff0c;即布隆过滤器 2.布隆过滤器的查找 3.布隆过滤器的删除 4.布隆过滤器优点 5、布隆过滤器缺陷 三、海量数据处理问题&#xff1a; 一、位图 问题1&#xff1a;给40亿个不…

【阅读论文】When Large Language Models Meet Vector Databases: A Survey

摘要 本调查探讨了大型语言模型&#xff08;LLM&#xff09;和向量数据库&#xff08;VecDB&#xff09;之间的协同潜力&#xff0c;这是一个新兴但迅速发展的研究领域。随着LLM的广泛应用&#xff0c;出现了许多挑战&#xff0c;包括产生虚构内容、知识过时、商业应用成本高昂…

day01_mysql_课后练习 - 参考答案

文章目录 day01_mysql_课后练习第1题第2题第3题第4题第5题 day01_mysql_课后练习 第1题 案例&#xff1a; 1、创建数据库day01_test01_library 2、创建表格books 字段名字段说明数据类型允许为空唯一b_id书编号int(11)否是b_name书名varchar&#xff08;50&#xff09;否否…

章节10实验--Ubuntu18.04 Qt MySQL libqsqlmysql.so

前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容&#xff0c;所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者&#xff1a;房胜、李旭健、黄…

SAP SD模块影响MRP结果的几个因素

后台最近会收到小伙伴的私信说,我的销售订单已经下达了,但是MRP仍然没有跑出结果,没有跑出需求。遇到这种情况我们就需要一个个地方去进行分析,看哪里的数据存在问题,系统的配置存在问题导致的。接下来文章中将会分析SD销售模块哪些配置点会影响到MRP的运行。 1、首先遇到…

【Web】浅聊Hessian异常toString姿势学习复现

目录 前言 利用关键 调用分析 如何控制第一个字节 EXP 前言 Hessian CVE-2021-43297&#xff0c;本质是字符串和对象拼接导致隐式触发了该对象的 toString 方法&#xff0c;触发toString方法便可生万物&#xff0c;而后打法无穷也&#xff01; 这个CVE针对的是Hessian2I…

5G智能网关助力工业铸造设备监测升级

随着物联网技术的迅猛发展和工业4.0浪潮的推进&#xff0c;传统工业正面临着严峻的转型升级压力。在这一背景下&#xff0c;铸造行业——这一典型的传统重工业领域&#xff0c;也必须积极探索借助5G、物联网、边缘计算等技术提升生产经营效率的新路径。 本文就基于佰马合作伙伴…

C++初阶 | [九] list 及 其模拟实现

摘要&#xff1a;介绍 list 容器&#xff0c;list 模拟实现&#xff0c;list与vector的对比 list&#xff08;带头双向循环列表&#xff09; 导入&#xff1a;list 的成员函数基本上与 vector 类似&#xff0c;具体内容可以查看相关文档(cplusplus.com/reference/list/list/)&…