当前位置: 首页 > news >正文

OJ题-合并K个已排序的链表

描述

合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。

数据范围:节点总数 0≤n≤50000≤n≤5000,每个节点的val满足 ∣val∣<=1000∣val∣<=1000

要求:时间复杂度 O(nlogn)O(nlogn)

下面给出C++代码的两种方法:

方法1:使用优先队列(最小堆)

优先队列可以很方便地处理多个链表头节点的最小值,每次从 K 个链表中取出最小的节点,合并到结果链表中。

思路:

  1. 使用优先队列(最小堆)来存储每个链表的当前头节点。
  2. 每次从堆中取出最小值节点,并将它的下一个节点重新加入堆。

重复这个过程,直到所有链表都被合并。

#include <queue>
#include <vector>
#include <iostream>struct ListNode {int val;ListNode* next;ListNode(int x) : val(x), next(nullptr) {}
};// 比较器,用于优先队列
struct Compare {bool operator()(ListNode* a, ListNode* b) {return a->val > b->val;}
};class Solution {
public:ListNode* mergeKLists(std::vector<ListNode*>& lists) {// 使用优先队列(最小堆)std::priority_queue<ListNode*, std::vector<ListNode*>, Compare> minHeap;// 初始化:将每个链表的头节点加入优先队列for (auto node : lists) {if (node) {minHeap.push(node);}}// 哑节点,便于构建新链表ListNode* dummy = new ListNode(0);ListNode* cur = dummy;// 逐步从最小堆中取出最小的节点,并更新链表while (!minHeap.empty()) {// 取出最小值节点ListNode* minNode = minHeap.top();minHeap.pop();// 将最小节点接到新链表的末尾cur->next = minNode;cur = cur->next;// 如果最小节点的下一个节点不为空,将其加入堆中if (minNode->next) {minHeap.push(minNode->next);}}// 返回合并后的链表return dummy->next;}
};

分析:

1、优先队列的使用

  • 优先队列使用自定义比较器 Compare,使得最小的节点始终位于堆顶。
  • 每次从堆顶取出最小的节点,并将它的 next 节点放入堆中。

2、时间复杂度O(N log K),其中 N 是所有链表节点的总数,K 是链表的个数。每次从优先队列取出最小元素的时间复杂度为 O(log K),一共需要执行 N 次。

3、空间复杂度O(K),优先队列最多存储 K 个元素。

方法2:分治法

可以使用分治法逐步将 K 个链表两两合并,类似于归并排序的过程。每次两两合并直到只剩一个链表。

思路:

  1. K 个链表分成两部分,分别合并。
  2. 不断递归分治,直到只剩下两个链表,将它们合并。
  3. 最终得到合并后的链表。
    class Solution {
    public:// 合并两个有序链表ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {if (!l1) return l2;if (!l2) return l1;if (l1->val < l2->val) {l1->next = mergeTwoLists(l1->next, l2);return l1;} else {l2->next = mergeTwoLists(l1, l2->next);return l2;}}// 分治法合并 K 个链表ListNode* mergeKLists(std::vector<ListNode*>& lists) {if (lists.empty()) return nullptr;return mergeKListsHelper(lists, 0, lists.size() - 1);}// 分治递归函数ListNode* mergeKListsHelper(std::vector<ListNode*>& lists, int left, int right) {if (left == right) return lists[left];int mid = left + (right - left) / 2;ListNode* l1 = mergeKListsHelper(lists, left, mid);ListNode* l2 = mergeKListsHelper(lists, mid + 1, right);return mergeTwoLists(l1, l2);}
    };
    

    分析:

1、分治递归

  • 使用递归将链表划分为两部分,每次递归调用 mergeKListsHelper 合并两部分链表,直到只剩下两个链表。
  • 通过 mergeTwoLists 函数合并两个链表。

2、时间复杂度O(N log K),其中 N 是所有节点的总数,K 是链表的个数。分治法的递归树的高度为 log K,每次合并的时间复杂度为 O(N)

3、空间复杂度O(log K),由于递归调用栈的深度为 log K

总结:

优先队列法适合需要立即获取最小节点的情况,效率较高。

分治法适合逐步合并的方式,利用了归并排序的思想,递归实现较为直观。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • libmodbus:写一个modbusTCP服务
  • 【AI学习】AI绘画发展简史
  • Unreal像素流ubantu os部署细节
  • 使用Maven创建一个Java项目并在repository中使用
  • qwen2 VL 多模态图文模型;图像、视频使用案例
  • ElK 8 收集 Nginx 日志
  • windows server2012 配制nginx安装为服务的时候,直接跳要安装.net框架,用自动的安装,直接失败的解决。
  • 从入门到精通,带你探索适合新手的视频剪辑工具
  • STM32快速复习(十二)FLASH闪存的读写
  • 海外服务器哪个速度最快且性能稳定
  • 鸿萌数据恢复服务: 修复 Windows, Mac, 手机中 “SD 卡无法读取”错误
  • 【git系列】git中的那些迷惑的术语以及概念详解
  • Linux(ubuntu)(c语言程序)
  • 算法训练——day16快乐数
  • 硬件开篇——体系架构
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • 【node学习】协程
  • 11111111
  • android 一些 utils
  • co.js - 让异步代码同步化
  • es的写入过程
  • HomeBrew常规使用教程
  • Logstash 参考指南(目录)
  • MySQL-事务管理(基础)
  • React的组件模式
  • windows下mongoDB的环境配置
  • 飞驰在Mesos的涡轮引擎上
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 前端知识点整理(待续)
  • 突破自己的技术思维
  • 我建了一个叫Hello World的项目
  • ​学习笔记——动态路由——IS-IS中间系统到中间系统(报文/TLV)​
  • # 日期待t_最值得等的SUV奥迪Q9:空间比MPV还大,或搭4.0T,香
  • (0)Nginx 功能特性
  • (24)(24.1) FPV和仿真的机载OSD(三)
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (Java入门)学生管理系统
  • (LeetCode 49)Anagrams
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (一)UDP基本编程步骤
  • (一)插入排序
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转)Sql Server 保留几位小数的两种做法
  • (转)人的集合论——移山之道
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • .net core Swagger 过滤部分Api
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .Net语言中的StringBuilder:入门到精通
  • .py文件应该怎样打开?
  • [2016.7 day.5] T2
  • [Assignment] C++1
  • [Bzoj4722]由乃(线段树好题)(倍增处理模数小快速幂)