题目描述

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

示例:

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

https://leetcode-cn.com/problems/merge-k-sorted-lists/

解法1

题目要求合并K个有序链表, 我们不妨先考虑合并两个有序链表. 为了便于操作, 我们创建一个头节点head, 该节点的value字段没有意义. 待合并的两个链表分别记为l1与l2, 为了保持合并后的链表仍然有序, 我们每次都从l1与l2中挑选当前最小的节点, 然后将其插入到头节点head.

现有链表l1, l2, 头节点head

p = head

if (l1.val < l2.val) { // 选取l1, l2当前最小的节点

p.next = l1;

l1 = l1.next;

} else {

p.next = l2;

l2 = l2.next;

}

p = p.next;

添加一个节点到存放结果的有序链表head中

上述代码片段仅仅完成了从l1或l2中取一个节点合并到有序链表head中, 我们需要加一个循环, 用尽l1或l2链表中任意一个. 因为l1与l2链表可能不等长, 即使他们等长也不一定被同时用尽. 例如l1=1->1->1->1, l2=2->2. 那么l1一定是先于l2被用尽. 因此, 当他们任意一个被用尽, 我们应当将未被用尽的链表接到head链表后(下面代码的18,20行所示). 下面的代码片段实现了将两个有序链表合并, 并返回被合并的有序链表的第一个节点.

    private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(0);
        ListNode p = head;

        while (l1 != null &amp;&amp; l2 != null) {
            if (l1.val < l2.val) {
                p.next = l1;
                l1 = l1.next;

            } else {
                p.next = l2;
                l2 = l2.next;
            }
            p = p.next;
        }

        if (l1 != null)
            p.next = l1;
        else
            p.next = l2;

        return head.next;
    }

题目要求将K个有序链表合并, 我们可以将K个链表先取两个合并, 被合并的链表记为tmp. 那么, K个链表还剩下K-2个链表待被合并, 我们依次将他们合并到tmp中. 计作tmp = mergeTwoLists(tmp, lists[i]), 2<=i<|lists|. 最后, 我们需要注意几个特例, 一个是待被合并的链表lists为空, 那么我们直接返回空链表. 如果待被合并的链表lists中只有一个链表, 我们直接返回那一个链表即可. 全部代码如下.

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(0);
        ListNode p = head;

        while (l1 != null &amp;&amp; l2 != null) {
            if (l1.val < l2.val) {
                p.next = l1;
                l1 = l1.next;

            } else {
                p.next = l2;
                l2 = l2.next;
            }
            p = p.next;
        }

        if (l1 != null)
            p.next = l1;
        else
            p.next = l2;

        return head.next;
    }

    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length < 1)
            return null;
        if (lists.length < 2)
            return lists[0];

        ListNode tmp = mergeTwoLists(lists[0], lists[1]);

        for (int i = 2; i < lists.length; i++) {
            tmp = mergeTwoLists(tmp, lists[i]);
        }

        return tmp;
    }
}
pwrliang Algorithms, LinkedList

Leave a Reply

Your email address will not be published. Required fields are marked *