[LeetCode题解]23. 合并K个升序链表 | 分治 + 递归

方法一:分治 + 递归

解题思路

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)\) 空间代价的栈空间。
posted @ 2020-11-21 16:41  大杂草  阅读(303)  评论(0编辑  收藏  举报