方法一:分治 + 递归

解题思路

21. 合并两个有序链表,我们知道如何合并两个有序链表。而本题是合并 k 个有序链表,可以通过大问题拆分成小问题解决,即把 k 个链表,拆分成 k/2 个链表组,俩俩合并,直到合并成一个链表,这就是分而治之的思想。

可以通过递归来实现分治算法:

  1. 定义函数功能:合并链表数组中的 leftright 个链表
  2. 结束条件:left == right,即只剩下一个链表,无须合并,直接返回
  3. 递推公式:将 [left, right] 拆分成两半,分别获得左边已合并的链表 l1 和右边已合并的链表 l2,然后再对这两个链表进行合并。

代码

/**
* Definition for singly-linked list.
* public class ListNode {
* public int val;
* public ListNode next;
* public ListNode(int val=0, ListNode next=null) {
* this.val = val;
* this.next = next;
* }
* }
*/
public class Solution {
public ListNode MergeKLists(ListNode[] lists) {
if(lists == null || lists.Length == 0) {
return null;
} return MergeKLists(lists, 0, lists.Length-1);
} private ListNode MergeKLists(ListNode[] lists, int left, int right) {
if(left == right) {
return lists[left];
}
int mid = left + (right-left)/2;
ListNode l1 = MergeKLists(lists, left, mid);
ListNode l2 = MergeKLists(lists, mid+1, right); return MergeTwoLists(l1, l2);
} private ListNode MergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null) {
return l2;
}
if(l2 == null) {
return l1;
} ListNode dummy = new ListNode();
ListNode p1 = l1, p2 = l2, cur = dummy;
while(p1 != null && p2 != null) {
if(p1.val < p2.val) {
cur.next = p1;
cur = cur.next;
p1 = p1.next;
} else {
cur.next = p2;
cur = cur.next;
p2 = p2.next;
}
} cur.next = p1 == null ? p2 : p1; return dummy.next;
}
}

复杂度分析

  • 时间复杂度:\(O(n*k*logk)\),其中链表数组长度为 \(k\),链表的平均长度为 \(n\)。函数 MergeKLists 的时间复杂度为 \(O(klogk)\)(分治),函数 MergeTwoLists 的时间复杂度是 \(O(n)\),因此总的时间复杂度为 \(O(n*k*logk)\)。
  • 空间复杂度:\(O(logk)\),递归会使用到 \(O(logk)\) 空间代价的栈空间。

[LeetCode题解]23. 合并K个升序链表 | 分治 + 递归的更多相关文章

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

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

  2. 【LeetCode】23.合并K个排序链表

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  10. 【23. 合并K个排序链表】【困难】【优先队列/堆排序】

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

随机推荐

  1. C++11新特性:Lambda函数(匿名函数)

    声明:本文参考了Alex Allain的文章http://www.cprogramming.com/c++11/c++11-lambda-closures.html 加入了自己的理解,不是简单的翻译 ...

  2. sql 统计用的sql

    mh:工时   mhtype:工时类型(6种) 字段:userid      mhtype    mh       001          1        5       001          ...

  3. 一个消除if语句的例子

    // 一个按钮点击事件,判断点击按钮是那一个显示出他的信息 - (IBAction)buttonPressed:(id)sender { if (sender == self.leftButton) ...

  4. 转载:js和jquery获取父级元素、子级元素、兄弟元素的方法

    转载网址: 先说一下JS的获取方法,其要比JQUERY的方法麻烦很多,后面以JQUERY的方法作对比. JS的方法会比JQUERY麻烦很多,主要则是因为FF浏览器,FF浏览器会把你的换行也当最DOM元 ...

  5. 创建 Rex-Ray volume - 每天5分钟玩转 Docker 容器技术(76)

    前面我们安装部署了 Rex-Ray,并且成功配置 VirtualBox backend,今天演示如何创建和使用 Rex-Ray volume. 在 docker1 或 docker2 上执行如下命令创 ...

  6. 两台主机,ssh端口不同,如何拷贝文件

    A主机ip:172.26.225.199 ssh端口12995 B主机ip:172.26.225.200 ssh端口12991 将B主机的文件拷贝到A主机 [root@test2019030517 s ...

  7. VBS弹出来的对话框如何置顶!--果然技巧

    msgbox 第二参数+4096 mshta vbscript:msgbox("提示内容6",6,"提示窗口6")(window.close)

  8. Day 02 编程语言介绍及运行python

    一.编程语言介绍 1.1.机器语言:直接用计算机能理解的二进制指令编写程序,直接控制硬件. 1.2.汇编语言:用英文标签取代二进制指令编写程序,本质也是在直接控制硬件. 1.3.高级语言:用人能理解的 ...

  9. 用C/C++开发android应用

    在某些情况下,比如原来与很多c/c++的代码, 可能希望采用c/c++编写android应用程序.在这种情况下,一般使用NDK.但是由于android直提供了java接口,因此不能够直接调用andro ...

  10. virtio前端驱动详解

    2016-11-08 前段时间大致整理了下virtIO后端驱动的工作模式以及原理,今天就从前端驱动的角度描述下目前Linux内核代码中的virtIO驱动是如何配合后端进行工作的. 注:本节代码参考Li ...