[100天算法】-合并K个升序链表(day 56)

题目描述

给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。示例 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来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

方法1:顺序合并

思路

跟 21.合并两个有序链表 的基本思路是一样的,只不过每轮操作需要比较 k 个链表节点的值。

复杂度分析

  • 时间复杂度:$O(k*n)$,k 是链表个数,n 是合并后链表的长度。
  • 空间复杂度:$O(1)$。

代码(JavaScript/C++)

JavaScript Code

/*** Definition for singly-linked list.* function ListNode(val, next) {*     this.val = (val===undefined ? 0 : val)*     this.next = (next===undefined ? null : next)* }*/
/*** @param {ListNode[]} lists* @return {ListNode}*/
var mergeKLists = function (lists) {if (!lists || !lists.length) return null;let dummy = new ListNode();let tail = dummy;while (!isEmpty(lists)) {const min = getMin(lists);tail.next = new ListNode(min.val);tail = tail.next;}return dummy.next;// **********************************************function getMin(lists) {let minIndex = -1,minNode = new ListNode(Infinity);for (let i = 0; i < lists.length; i++) {const node = lists[i];if (node && node.val < minNode.val) {minNode = node;minIndex = i;}}lists[minIndex] = minNode.next;return minNode;}function isEmpty(lists) {return lists.every(n => n === null);}
};

C++ code

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
private:bool isEmpty_(vector<ListNode*>& lists) {for (int i = 0; i < lists.size(); i++) {if (lists[i]) return false;}return true;}int getMinVal_(vector<ListNode*>& lists) {int ans = INT_MAX;int idx = -1;for (int i = 0; i < lists.size(); i++) {if (lists[i] && lists[i]->val < ans) {ans = lists[i]->val;idx = i;}}lists[idx] = lists[idx]->next;return ans;}public:ListNode* mergeKLists(vector<ListNode*>& lists) {ListNode* dummy = new ListNode();ListNode* tail = dummy;while (!isEmpty_(lists)) {int min_val = getMinVal_(lists);tail->next = new ListNode(min_val);tail = tail->next;}return dummy->next;}
};

方法2:顺序合并+堆

思路

跟 方法1 思路一致,不过用了堆来寻找 k 个链表节点中的最小值。

复杂度分析

  • 时间复杂度:$O(nlogk)$,k 是链表个数,n 是合并后链表的长度。
  • 空间复杂度:$O(k)$,k 是链表个数,堆的空间大小。

代码

JavaScript Code

/*** Definition for singly-linked list.* function ListNode(val, next) {*     this.val = (val===undefined ? 0 : val)*     this.next = (next===undefined ? null : next)* }*/
/*** @param {ListNode[]} lists* @return {ListNode}*/
var mergeKLists = function (lists) {if (!lists || !lists.length) return null;let dummy = new ListNode();let tail = dummy;const heap = new MinHeap(lists.filter(Boolean), function comparator(inserted, compared) {return inserted.val > compared.val;});while (heap.size() > 0) {const min = heap.pop();tail.next = new ListNode(min.val);tail = tail.next;min.next && heap.insert(min.next)}return dummy.next;
};// **************************************************class Heap {constructor(list = [], comparator) {this.list = list;this.comparator = comparator;this.init();}init() {const size = this.size();for (let i = Math.floor(size / 2) - 1; i >= 0; i--) {this.heapify(this.list, size, i);}}insert(n) {this.list.push(n);const size = this.size();for (let i = Math.floor(size / 2) - 1; i >= 0; i--) {this.heapify(this.list, size, i);}}peek() {return this.list[0];}pop() {const last = this.list.pop();if (this.size() === 0) return last;const returnItem = this.list[0];this.list[0] = last;this.heapify(this.list, this.size(), 0);return returnItem;}size() {return this.list.length;}
}class MinHeap extends Heap {constructor(list, comparator) {if (typeof comparator != 'function') {comparator = function comparator(inserted, compared) {return inserted > compared;};}super(list, comparator);}heapify(arr, size, i) {let smallest = i;const left = Math.floor(i * 2 + 1);const right = Math.floor(i * 2 + 2);if (left < size && this.comparator(arr[smallest], arr[left]))smallest = left;if (right < size && this.comparator(arr[smallest], arr[right]))smallest = right;if (smallest !== i) {[arr[smallest], arr[i]] = [arr[i], arr[smallest]];this.heapify(arr, size, smallest);}}
}

方法3:分治

思路

  • 将 k 个链表平均分成两份,分别进行合并后,再将两个结果进行合并。
  • 最后一步就是简单的 合并两个有序链表。
  • 而中间的步骤也很简单,只需要将 k/2 个链表再细分,再细分,细分到一次只需要处理两个链表就好了。

复杂度分析

  • 时间复杂度:$O(nlogk)$,k 是链表个数,n 是合并后链表的长度。
  • 空间复杂度:$O(k)$,k 是链表个数,堆的空间大小。

代码(JavaScript/C++)

JavaScript Code

/*** Definition for singly-linked list.* function ListNode(val, next) {*     this.val = (val===undefined ? 0 : val)*     this.next = (next===undefined ? null : next)* }*/
/*** @param {ListNode[]} lists* @return {ListNode}*/
var mergeKLists = function(lists, start = 0, end = lists.length - 1) {if (start > end) return null;if (start === end) return lists[start];const mid = ((end - start) >> 1) + start;return mergeTwoLists(mergeKLists(lists, start, mid), mergeKLists(lists, mid + 1, end));
};function mergeTwoLists(l1, 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;}
}

C++ Code

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* mergeKLists(vector<ListNode*>& lists) {return mergeKLists(lists, 0, lists.size() - 1);}ListNode* mergeKLists(vector<ListNode*>& lists, int start, int end) {if (start > end) return nullptr;if (start == end) return lists[start];int m = (end - start) / 2 + start;return merge2Lists(mergeKLists(lists, start, m), mergeKLists(lists, m + 1, end));}ListNode* merge2Lists(ListNode* l1, ListNode* l2) {if (!l1) return l2;if (!l2) return l1;if (l1->val < l2->val) {l1->next = merge2Lists(l1->next, l2);return l1;} else {l2->next = merge2Lists(l1, l2->next);return l2;}}
};

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

口袋参谋:如何玩转手淘“问大家”?这招超好用!

​现在应该不会还有商家不知道&#xff0c;手淘“问大家”分析吧&#xff01; “问大家”模块对于转化率的影响非常关键&#xff0c;它的影响力不亚于买家秀&#xff0c;以前买家下单前都会去参考买家秀&#xff0c;现在买家更倾向于参考“问大家”然而&#xff0c;真正玩转“问…

win10系统nodejs的安装npm教程

1.在官网下载nodejs&#xff0c;https://nodejs.org/en 2&#xff0c;双击nodejs的安装包 3&#xff0c;点击 next 4&#xff0c;勾选I accpet the terms in…… 5&#xff0c;第4步点击next进入配置安装路径界面 6,点击next&#xff0c;选中Add to PATH &#xff0c;旁边…

集简云浏览器插件:无代码开发,实现CRM系统与用户运营的高效集成

无代码开发实现连接 集简云浏览器插件是一种强大的工具&#xff0c;可以帮助公司实现网页端数据的自动化同步&#xff0c;例如新闻媒体网站的数据抓取和采集&#xff0c;以及每天同步文章和视频等最新营销数据。这种插件的功能使得企业可以在没有编程技能的情况下实现无代码开…

【蓝桥杯选拔赛真题44】python小蓝晨跑 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析

目录 python小蓝晨跑 一、题目要求 1、编程实现 2、输入输出 二、算法分析

国内某发动机制造工厂RFID智能制造应用解决方案

一、工厂布局和装备 国内某发动机制造工厂的装配车间布局合理&#xff0c;设备先进&#xff0c;在这个5万平方米的生产区域内&#xff0c;各个工位之间流程紧密&#xff0c;工厂采用了柔性设备&#xff0c;占比达到了67%&#xff0c;数控化率超过90%&#xff0c;自动化率达到了…

若依笔记(三):权限控制与数据隔离

目录 数据隔离/权限控制 用户/权限/部门/岗位 ​数据隔离 mybatis的maaper写法 注解和切面 前端路由拦截 已知若依单体的前端采用vue-element-admin&#xff0c;在前端的专栏系列vue-element-admin的动态路由已详细拆解&#xff0c;其最大特点是使用后端返回数据控制前端…

react和vue的区别

目录 react和vue区别的主要区别 react和vue区别的部分详情 1. 语法&#xff1a; 2. 组件化开发&#xff1a; 3. 状态管理&#xff1a; 4. 生态系统&#xff1a; 5. 性能特点&#xff1a; react和vue区别的主要区别 React和Vue是两种流行的JavaScript库&#xff0c;用于构…

pom.xml详解

我们在开发Java应用程序时&#xff0c;pom.xml文件是项目中的核心配置文件之一&#xff0c;它结合Maven实现对项目依赖的拉取&#xff0c;今天就详细了解一下pom.xml文件的配置 Maven是一种构建工具&#xff0c;它用于构建、管理和发布Java项目pom.xml文件包含了项目的所有重要…

降低边际成本:跨境电商的利润增长策略

在竞争激烈的跨境电商领域&#xff0c;降低成本是提高利润的关键。边际成本&#xff0c;即生产或销售一件额外商品所需的额外成本&#xff0c;在跨境电商中起到至关重要的作用。在本文中&#xff0c;我们将探讨降低边际成本的策略&#xff0c;以实现跨境电商的利润增长。 供应链…

苹果M3 Max芯片跑分曝光:GPU性能不及M2 Ultra

驱动中国2023年11月2日消息&#xff0c;近日&#xff0c;据外媒报道&#xff0c;在苹果 M3 芯片现身 GeekBench 跑分库之后&#xff0c;M3 Max 芯片也出现在该跑分平台上。 据悉&#xff0c;搭载 M3 Max 芯片的设备标识符为 Mac15,9&#xff0c;目前共有 4 条信息&#xff0c;其…

【Linux】Nignx的入门使用负载均衡动静分离(前后端项目部署)---超详细

一&#xff0c;Nignx入门 1.1 Nignx是什么 Nginx是一个高性能的开源Web服务器和反向代理服务器。它使用事件驱动的异步框架&#xff0c;可同时处理大量请求&#xff0c;支持负载均衡、反向代理、HTTP缓存等常见Web服务场景。Nginx可以作为一个前端的Web服务器&#xff0c;也可…

微信小程序:实现多个按钮提交表单

效果 核心步骤 通过data-type给不同按钮进行设置&#xff0c;便于很好的区分不同按钮执行不同功能 data-type"" 完整代码 wxml <form action"" bindsubmit"formSubmit"><button style"margin-bottom:5%" data-type"pa…

IDEA创建Springboot多模块项目

一、创建父模块 File --> New --> Project &#xff0c;选择 “ Spring Initalizr ” &#xff0c;点击 Next Next Next --> Finish 二、创建子模块 右键根目录&#xff0c;New --> Module 选择 “ Spring Initializr ”&#xff0c;点击Next 此处注意T…

Springboot JSP项目如何以war、jar方式运行

文章目录 一&#xff0c;序二&#xff0c;样例代码1&#xff0c;代码结构2&#xff0c;完整代码备份 三&#xff0c;准备工作1. pom.xml 引入组件2. application.yml 指定jsp配置 四&#xff0c;war方式运行1. 修改pom.xml文件2. mvn执行打包 五&#xff0c;jar方式运行1. 修改…

R语言绘图-5-条形图(修改坐标轴以及图例等)

0. 说明&#xff1a; 1. 绘制条形图&#xff1b; 2. 添加文本并调整位置&#xff1b; 3. 调整x轴刻度的字体、角度及颜色&#xff1b; 4. 在导出pdf时&#xff0c;如果没有字体&#xff0c;该怎么解决问题&#xff1b; 1. 结果&#xff1a; 2. 代码&#xff1a; library(ggp…

UE5数字孪生制作(一) - QGIS 学习笔记

1.下载 QGIS是免费的GIS工具&#xff0c;下载地址&#xff1a; https://www.qgis.org/en/site/ 2.安装 - 转中文 按照步骤安装&#xff0c;完成后&#xff0c;在菜单 设置settings里&#xff0c;选择options&#xff0c;修改语言 确定后&#xff0c;需要重启下软件 3.学习视…

MATLAB和西门子SMART PLC OPC通信

西门子S7-200SMART PLC OPC软件的下载和使用,请查看下面文章 Smart 200PLC PC Access SMART OPC通信_基于pc access smart的opc通信_RXXW_Dor的博客-CSDN博客文章浏览阅读2.7k次,点赞2次,收藏5次。OPC是一种利用微软COM/DCOM技术达成自动控制的协议,采用典型的C/S模式,针…

测试用例设计——WEB通用测试用例

现在项目做完了&#xff0c;我觉得还是有必要总结一下&#xff0c;学习到的内容。毕竟有总结才能有提高嘛&#xff01;总结一下通用的东西&#xff0c;不管什么项目基本都可能会遇到&#xff0c;有写地方也有重复的或者有的是按照个人的习惯来总结的不一定都对&#xff0c;有不…

Visual Components Robotics OLP解决方案 北京衡祖

Visual Components 引入了“Visual Components Robotics OLP”的重大升级&#xff0c;合并了制造模拟和机器人离线编程。该解决方案利用 Delfoi Robotics 的技术&#xff0c;提高生产率、减少停机时间并减少浪费。 一、探索下一代离线机器人编程软件 自 1999 年以来&#xff0…

【计算机网络】应用层

应用层协议原理 客户-服务器体系结构&#xff1a; 特点&#xff1a;客户之间不能直接通信&#xff1b;服务器具有周知的&#xff0c;固定的地址&#xff0c;该地址称为IP地址。 配备大量主机的数据中心常被用于创建强大的虚拟服务器&#xff1b;P2P体系结构&#xff1a; 特点&…