题目描述

23.合并K个排序链表

合并k个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6

题目解析

方法一:暴力法

解题思路

合并K个排序链表,首先我们直接采用暴力法去解决,将链表所有节点的val值放入一个List中,然后将这个List进行排序,根据排序后的List重新构建新链表。

代码示例

Java:

/**
* Definition for singly-linked list.
*/
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
} class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) return null; // 1. 将链表节点放入一个List中
List<Integer> arr = new ArrayList<Integer>();
for (int i = 0; i < lists.length; i++) {
ListNode cur = lists[i];
while(cur != null) {
arr.add(cur.val);
cur = cur.next;
}
} // 2. 排序
Collections.sort(arr); // 3. 重新构建链表
ListNode res = new ListNode(0);
ListNode cur = res;
for(int i = 0; i < arr.size(); i++) {
ListNode node = new ListNode(arr.get(i));
cur.next = node;
cur = cur.next;
}
return res.next;
}
}

复杂度分析

时间复杂度:O(N * log(N)), N代表所有链表节点数量。

  • 遍历所有值需要花费O(N)时间
  • 稳定的排序算法花费N * log(N)时间
  • 重新构建链表需要花N * log(N)时间

空间复杂度:O(N)

方法二:堆排序法

解题思路

采用堆的方式来进行链表节点的排序,创建一个大小为K的小根堆,首先将K个链表的头指针插入到堆中,然后取出堆顶元素,同时将堆顶元素的下一个节点插入到最小堆中,然后循环该操作直至链表节点全部遍历完成。

代码示例

Java:

/**
* Definition for singly-linked list.
*/
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
} class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) return null; // 1. 初始化小根堆
PriorityQueue<ListNode> queue = new PriorityQueue(new Comparator<ListNode>() {
public int compare(ListNode o1, ListNode o2) {
return (o1.val - o2.val);
}
});
for(int i = 0; i < lists.length; i++) {
if (lists[i] != null) queue.add(lists[i]);
} // 2. 取出堆顶元素,并将堆顶元素的下一节点插入小根堆
ListNode res = new ListNode(0);
ListNode cur = res;
while(!queue.isEmpty()) {
ListNode top = queue.poll();
if (top.next != null) {
queue.add(top.next);
}
cur.next = top;
cur = cur.next;
}
return res.next;
}
}

复杂度分析

时间复杂度:O(N * log(K)),N代表所有链表节点数量,K代表链表的个数。

空间复杂度:O(K)

方法三:分治法

解题思路

我们将K个链表对半划分,先合并前K/2个链表,再合并后K/2个链表,然后将前K/2个链表合并成的链表再与后K/2个链表合并的链表进行合并,得到最终结果。

在处理前K/2个和后K/2个链表时,就跟上述方法思路一致,通过递归的方式不停的将链表进行划分,直到链表无法继续划分为止,将链表返回给递归的上一层进行两两合并。

分治思路:划分子问题 --> 合并子问题结果【递归实现】

代码示例

Java:

/**
* Definition for singly-linked list.
*/
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
} class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists == null || lists.length == 0) return null;
return divide(lists, 0, lists.length-1);
} public ListNode divide(ListNode[] lists, int lo, int hi) {
if (lo == hi) return lists[lo];
int mid = lo + (hi - lo) / 2;
ListNode left = divide(lists, lo, mid);
ListNode right = divide(lists, mid + 1, hi);
return merge(left, right);
} public ListNode merge(ListNode l1, ListNode l2) {
if(l1 == null || l2 == null) {
return (l1 == null) ? l2 : l1;
}
if(l1.val <= l2.val) {
l1.next = merge(l1.next,l2);
return l1;
} else {
l2.next = merge(l1, l2.next);
return l2;
}
}
}

复杂度分析

时间复杂度:O(N * log(K)),N代表所有链表节点数量,K代表链表的个数。

空间复杂度:O(K)

【LeetCode】23.合并K个排序链表的更多相关文章

  1. LeetCode 23. 合并K个排序链表(Merge Two Sorted Lists)

    23. 合并K个排序链表 23. Merge k Sorted Lists 题目描述 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. LeetCode23. Merge k S ...

  2. Java实现 LeetCode 23 合并K个排序链表

    23. 合并K个排序链表 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输 ...

  3. [LeetCode]23. 合并K个排序链表(优先队列;分治待做)

    题目 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [   1->4->5,   1->3->4,   2->6 ] 输出: 1 ...

  4. [LeetCode] 23. 合并K个排序链表

    题目链接: https://leetcode-cn.com/problems/merge-k-sorted-lists/ 题目描述: 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂 ...

  5. leetcode 23. 合并K个排序链表 JAVA

    题目: 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [   1->4->5,   1->3->4,   2->6 ] 输出: ...

  6. LeetCode 23. 合并K个排序链表(Merge k Sorted Lists)

    题目描述 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [   1->4->5,   1->3->4,   2->6 ] 输出: ...

  7. LeetCode 23 ——合并 K 个排序链表

    1. 题目 2. 解答 2.1. 方法一 在 合并两个有序链表 的基础上,我们很容易想到第一种解法,首先我们将第一个链表和第二个链表合并成一个新的链表,然后再往后依次合并接下来的每个链表即可. 假设每 ...

  8. LeetCode题解-23 合并K个排序链表 Hard

    合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1-&g ...

  9. Leetcode题库——23.合并k个排序链表

    @author: ZZQ @software: PyCharm @file: mergeKLists.py @time: 2018/10/12 19:55 说明:合并 k 个排序链表,返回合并后的排序 ...

随机推荐

  1. angualrjs 总结 随记(一)

    $apply方法的作用 $apply方法是用来触发脏检查,它在控制器里监听一个变量,每当这个变量的值改变的时候,它会去与最初的值做一次比较,然后HTML页面就会及时更新该变量的值(将最新的值赋值到ht ...

  2. 《吐血整理》Redis 性能优化的 13 条军规!史上最全

    Redis 是基于单线程模型实现的,也就是 Redis 是使用一个线程来处理所有的客户端请求的,尽管 Redis 使用了非阻塞式 IO,并且对各种命令都做了优化(大部分命令操作时间复杂度都是 O(1) ...

  3. 动态规划-Maximum Subarray-Maximum Sum Circular Subarray

    2020-02-18 20:57:58 一.Maximum Subarray 经典的动态规划问题. 问题描述: 问题求解: public int maxSubArray(int[] nums) { i ...

  4. OpenAI的GPT-2:用Python构建世界上最先进的文本生成器的简单指南

    介绍 "The world's best economies are directly linked to a culture of encouragement and positive f ...

  5. .NET Core中创建和使用NuGet包

    在.NET Core的项目中,如果我们要在项目中引用其它DLL文件,不应该直接在项目引用中添加DLL文件(虽然在.NET Core项目中也可以这么做),建议是去直接下载DLL文件所属的NuGet包.这 ...

  6. 面试刷题27:程序员如何防护java界的新冠肺炎?

    背景 安全是软件设计的第二个非功能性需求,一般是当软件出现安全问题的时候才会得到重视. 最明显的比如 数据库用户信息和密码泄漏等: 数据加解密技术 单向加密 md5+salt值, 这个是软件设计中使用 ...

  7. python之路 2020/2/18

    这是第一篇随笔,记录今天的内容,我不知道什么是成功,因为我没有成功过,但是,我想成功一次! python 多练吧! 一.编程语言的分类 机器语言:01001010,高低电平,计算机懂的语言. 汇编语言 ...

  8. Android的安装

    基于VMware的Android虚拟机搭建 目录 基于VMware的Android虚拟机搭建 下载 安装 配置 使用 下载 进入VMware中国下载VMware Workstation Pro 进入f ...

  9. JS 剑指Offer(六) 用两个栈实现队列

    题目:用两个栈实现队列,实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入整数和在队列头部删除整数,若队列中没有元素deleteHead返回-1 分析:在队列的尾部插入 ...

  10. Javascript/Jquery实现日期前一天后一天

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...