1. 程式人生 > >leetCode 23. Merge k Sorted Lists (合併k個排序連結串列) 解題思路和方法

leetCode 23. Merge k Sorted Lists (合併k個排序連結串列) 解題思路和方法

Merge k Sorted Lists 

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

思路:此題是由合併兩個排序連結串列演化而來,剛開始,想法比較簡單,像求最大公共字首一樣,逐一求解;但是最後超時,所以馬上意識到出題方是為了使用歸併和分治的方法,故重新寫了程式碼。

程式碼一(超時未過):

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        int len = lists.length;
        if(len == 0){
            return null;
        }
        if(len == 1){
            return lists[0];
        }
        ListNode head = lists[0];
        for(int i = 0; i < len; i++){
            head = mergeTwoLists(head,lists[i]);
        }
        return head;
    }
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null || l2 == null)
            return l1 == null ? l2:l1;
        ListNode head = new ListNode(0);//定義一個頭結點
        ListNode p = head;
        ListNode temp = null;
        
        while(l1 != null && l2 != null){
            if(l1.val > l2.val){
                temp = l2;//用一個temp儲存現在的l1或l2
                l2 = l2.next;//l1或l2指標後移1位
            }else{
                temp = l1;
                l1 = l1.next;
            }//交換資料
            p.next = temp;
            p = p.next;
        }//temp取不為空的一個(也可能全為空)
        temp = l1 == null ?l2:l1;
        p.next = temp;//將剩餘的全部連結即可(上面的方法太囉嗦了)
        return head.next;
    }
}
程式碼二(通過):
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        int len = lists.length;
        //長度分別為<=1時的情況
        if(len == 0){
            return null;
        }
        if(len == 1){
            return lists[0];
        }
        ListNode[] ln = lists;
        while(len > 2){//大於等於2分而治之
            ln = merge(ln);//呼叫函式
            len = ln.length;//更新len
        }//最後兩個歸併
        ln[0] = mergeTwoLists(ln[0],ln[1]);
        return ln[0];
    }
    //對lists兩兩歸併
    public ListNode[] merge(ListNode[] lists){
        int len = lists.length;
        //兩兩歸併
        ListNode[] arr;
        //長度為偶數
        if((len & 1) == 0){
            arr = new ListNode[len/2];
        }else{//長度為奇數
            arr = new ListNode[len/2 + 1];
            arr[len/2] = lists[len - 1];//最後1位不參與歸併
        }//兩兩歸併實現;i < len-1;不能是i<len;不然報錯
        for(int i = 0; i < len - 1; i = i+2){
        	ListNode a = lists[i];
        	ListNode b = lists[i+1];
            arr[i/2] = mergeTwoLists(lists[i],lists[i+1]);//呼叫兩兩歸併方法
        }
        return arr;
    }
    
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null || l2 == null)
            return l1 == null ? l2:l1;
        ListNode head = new ListNode(0);//定義一個頭結點
        ListNode p = head;
        ListNode temp = null;
        
        while(l1 != null && l2 != null){
            if(l1.val > l2.val){
                temp = l2;//用一個temp儲存現在的l1或l2
                l2 = l2.next;//l1或l2指標後移1位
            }else{
                temp = l1;
                l1 = l1.next;
            }//交換資料
            p.next = temp;
            p = p.next;
        }//temp取不為空的一個(也可能全為空)
        temp = l1 == null ?l2:l1;
        p.next = temp;//將剩餘的全部連結即可(上面的方法太囉嗦了)
        return head.next;
    }
}