Merge k Sorted Lists

题意:给定k个链表,每个链表按升序排序,合并所有链表并返回链表头。

23. Merge k Sorted Lists (opens new window)

# 解法 1:暴搜

遍历所有链表,提取所有数字塞入一个新的list,对list排序,最后新建一个链表。空间复杂度O(n),时间复杂度O(nlogn)。

# 解法 2:优先级队列

利用Java的PriorityQueue实现最小堆,设置空间大小为k,具体的处理流程:先将k个链表塞入队列建立最小堆,然后退出一个节点塞入新的链表,如果这个节点还有下一个节点则塞入队列,重复这个动作直到队列为空。因为退出的节点是最小的,所以新的链表是升序排序的。空间复杂度O(n),时间复杂度O(nlongk)。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        // 优先级队列
        if (lists.length == 0) {
            return null;
        }
        PriorityQueue<ListNode> queue = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
            public int compare(ListNode a, ListNode b) {
                return a.val - b.val;
            }
        });
        for (int i = 0; i < lists.length; i++) {
            if (lists[i] != null) {
                queue.add(lists[i]);
            }
        }
        ListNode head = new ListNode(0);
        ListNode current = head;
        while (!queue.isEmpty()) {
            current.next = queue.poll();
            current = current.next;
            if (current.next != null) {
                queue.add(current.next);
            }
        }
        return head.next;
    }
}

# 解法 3:分治

参考快速幂的分治策略,可以将k个链表分治后一一合并。空间复杂度O(1),时间复杂度O(nlogk)。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        // 分治,双双合并
        if (lists.length == 0) {
            return null;
        }
        int len = lists.length;
        int interval = 1;
        while (interval < len) {
            for (int i = 0; i < len - interval; i += interval * 2) {
                lists[i] = mergeTwoLists(lists[i], lists[i + interval]);
            }
            interval *= 2;
        }
        return lists[0];
    }

    private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        var head = new ListNode(0);
        var cur = head;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            }  else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        if (l1 == null) {
            cur.next = l2;
        } else {
            cur.next = l1;
        }
        return head.next;
    }
}