K個排序鏈表的合併

問題描述;

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

示例:

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

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

解法一:

暴力求解,遍歷K個鏈表,找到其中頭結點最小的那個,將該節點插到合併鏈表的尾部,該節點後移。重複上述工作直到數組中k個排序鏈表都爲null。

實現代碼如下:

    public ListNode mergeKLists(ListNode[] lists) {
        ListNode head = new ListNode(-1);
        ListNode cur = head;
        boolean flag = true;//當所有的結點都遍歷完成後 置爲false
        while(flag){
            flag = false;
            int minValue = Integer.MAX_VALUE;
            for(int i = 0; i < lists.length; i++){
                if(lists[i] == null){
                    continue;
                }
                flag = true;
                minValue = lists[i].val < minValue ?  lists[i].val : minValue;
            }
            for(int i = 0; i < lists.length; i++){
                if(lists[i] == null){
                    continue;
                }
                if(minValue == lists[i].val){
                    cur.next = lists[i];
                    lists[i] = lists[i].next;
                    cur = cur.next;
                }
            }
        }
        return head.next;
    }

    假設每個鏈表長度爲N,則上述方法的時間複雜度爲O(k*k* N),由於總共K*N個元素,每個元素都需要經過K輪循環。

解法二:

使用歸併排序的思想,將lists數組中的鏈表兩兩合併,如此最終剩下一個大鏈表。爲了避免開闢新空間,總是將當前數組的兩端依次合併,並將結果保存在前面的位置上。該方式下每個節點不需要比較K次,只需log(K)即可。因此時間複雜度降爲O(log(k) * k * N)

實現代碼如下:

   
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(-1);
        ListNode cur = head;
        ListNode cur1 = l1;
        ListNode cur2 = l2;
        while(cur1 != null && cur2 != null){
            if(cur1.val < cur2.val){
                cur.next = cur1;
                cur1 = cur1.next;
            }else{
                cur.next = cur2;
                cur2 = cur2.next;
            }
            cur = cur.next;
        }
        if(cur1 != null){
            cur.next = cur1;
        }else{
            cur.next = cur2;
        }
        return head.next;
    }
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0){
            return null;
        }
        for(int end = lists.length - 1; end > 0; end = end / 2){
            step(lists, 0, end);
        }
        return lists[0];
    }
    public void step(ListNode[] lists, int start, int end){
        while(start < end){
            lists[start] = mergeTwoLists(lists[start], lists[end]);
            start++;
            end--;
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章