leetcode刷題(80)—— 23. 合併K個排序鏈表

合併 k 個排序鏈表,返回合併後的排序鏈表。請分析和描述算法的複雜度。

示例:

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

方法1:使用優先隊列合併
我們需要維護當前每個鏈表沒有被合併的元素的最前面一個,k個鏈表就最多有 k個滿足這樣條件的元素,每次在這些元素裏面選取 val 屬性最小的元素合併到答案中。在選取最小元素的時候,我們可以用優先隊列來優化這個過程。

class Solution {
  public static ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) return null;
        PriorityQueue<ListNode> queue = new PriorityQueue<>(lists.length, new Comparator<ListNode>() {
            @Override
            public int compare(ListNode o1, ListNode o2) {
                return o1.val - o2.val;
            }
        });
        for (int i = 0; i < lists.length; i++) {
             if (lists[i] != null) {
                queue.add(lists[i]);
            }
        }
        ListNode begin = new ListNode(-1);
        ListNode temp = begin;
        while (!queue.isEmpty()) {
            ListNode listNode = queue.poll();
            begin.next = listNode;
            begin = begin.next;
            if (begin.next != null) {
                queue.add(begin.next);
            }
        }
        return temp.next;
    }
}

複雜度
時間複雜度:考慮優先隊列中的元素不超過 k個,那麼插入和刪除的時間代價爲 O(logk),這裏最多有 kn個點,對於每個點都被插入刪除各一次,故總的時間代價即漸進時間複雜度爲 O(kn×logk)。
空間複雜度:這裏用了優先隊列,優先隊列中的元素不超過 kk 個,故漸進空間複雜度爲 O(k)。

方法2:使用分治

//方法2 使用分治
    public static ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) return null;
        return merge(lists, 0, lists.length - 1);
    }

    public static ListNode merge(ListNode[] lists, int left, int right) {
        if (left == right) return lists[left];
        int middle = left + (right - left) / 2;
        ListNode l1 = merge(lists, left, middle);
        ListNode l2 = merge(lists, middle + 1, right);
        return mergeTwoLists(l1, l2);
    }

    public static ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        if (l2 == null) return l1;
        if (l1.val < l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoLists(l2.next, l1);
            return l2;
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章