方法一:分治 + 递归

解题思路

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. 23. 合并K个排序链表 分治

    这种k个相同的子问题,可以两两分治,总的运算次数为logk 关键部分 int dis=1; int len=lists.size(); while(dis<=len) { for(int i=0 ...

  4. 浅谈归并排序:合并 K 个升序链表的归并解法

    在面试中遇到了这道题:如何实现多个升序链表的合并.这是 LeetCode 上的一道原题,题目具体如下: 用归并实现合并 K 个升序链表 LeetCode 23. 合并K个升序链表 给你一个链表数组,每 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Spring源码解析之基础应用(二)

    方法注入 在spring容器中,大部分bean的作用域(scope)是单例(singleton)的,少部分bean的作用域是原型(prototype),如果一个bean的作用域是原型,我们A bean ...

  2. lumen容器模仿

    <?php class Container { private $bindings = []; private $instances = []; public function getClosu ...

  3. spring boot:用swagger3生成接口文档,支持全局通用参数(swagger 3.0.0 / spring boot 2.3.2)

    一,什么是swagger? 1,  Swagger 是一个规范和完整的文档框架, 用于生成.描述.调用和可视化 RESTful 风格的 Web 服务文档 官方网站: https://swagger.i ...

  4. Python之集合详解

    定义: 1.不同元素组成 2.无序 3.集合中的元素必须是不可变类型 创建集合 s = {1,2,3,4,5,6,7,8} 1.定义可变集合 >>> set_test = set(' ...

  5. 不可不知的资源管理调度器Hadoop Yarn

    Yarn(Yet Another Resource Negotiator)是一个资源调度平台,负责为运算程序如Spark.MapReduce分配资源和调度,不参与用户程序内部工作.同样是Master/ ...

  6. 51nod1548 欧姆诺姆和糖果

    思路: 只有兩種糖果,枚舉其中一種糖果的數量就可以得到一個可行解: 但總有一種糖果的數量是較少的,並且該數量小於sqrt(C): 簡單證明: 1.若有任一糖果的質量大於sqrt(C),則必定有一糖果的 ...

  7. vue中跳转页面逻辑

    跳转详情页面具体代码 写这个页面需要安装两个 1.安装axios命令 Cnpm install axios --save 2.安装vant Cnpm install vant --save 在inde ...

  8. springboot添加拦截器

    一,编写拦截器 public class TokenInterceptor implements HandlerInterceptor { @Override public boolean preHa ...

  9. Mac下使用GitHub+Hexo搭建个人博客

    首发链接 开始之前需要在电脑上安装好Git和node.js,Mac上可以使用Homebrew命令行工具来安装Git和node.js 安装Homebrew 在命令行工具输入以下命令,如果已经安装过Hom ...

  10. java 内存可见性

    java线程 -> 线程工作内存 -> 主物理内存 线程工作内存的原理是栈内是连续的小空间,寻址速度比堆快得多,将变量拷贝到栈内生成副本再操作 什么是重排序 代码指令可能并不是严格按照代码 ...