算法題21. 合併兩個有序鏈表

21. 合併兩個有序鏈表

1、自己

我的第一個覺得好的方法是:爲兩個鏈各自設置一個指針,開始都指向第一個,然後比較,誰小就併入,指針向後。

這個想法佔空間,但是時間會剩下來。

我的第二個想法就是:以第一個鏈爲主,將第二個鏈的數挨個和第一個鏈的數進行比較(注意:不是從頭比較,因爲本來鏈就是按照大小的順序,所以可以從前一個數的位置開始往後比較)。

這個想法時間會久,但是剩空間。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        //判斷爲空
        if(l1 == null && l2 == null){
            return null;
        }
        
        //
        ListNode p1 = null;    //指向新鏈的開頭
        ListNode p2 = null;    //指向新鏈的末尾
        
        if((l1 != null) && (l2 == null || l1.val <= l2.val)){
            p1 = l1;
            p2 = l1;
            l1 = l1.next;
        }
        else if(l1 == null || l1.val > l2.val){
            p1 = l2;
            p2 = l2;
            l2 = l2.next;
        }
        while(l1 != null || l2 != null){
            if((l1 != null) && (l2 == null || l1.val <= l2.val)){
                p2.next = l1;
                p2 = l1;
                l1 = l1.next;
                continue;
            }
            if((l2 != null) && (l1 == null || l1.val > l2.val)){
                p2.next = l2;
                p2 = l2;
                l2 = l2.next;
                continue;
            }
        }
        return p1;
    }
}

提交錯誤:

1、還是在邏輯判斷上出現了問題,但是這個方法的邏輯判斷很複雜,很難一次性寫對。主要是在輸入值爲null的時候判斷較爲複雜

2、遞歸

看了一下官方的解答,使用的是遞歸的方法。感覺那個邏輯上的判斷要簡單的很多,代碼看起來也更加的簡介。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null){
            return l2;
        }else if(l2 == null){
            return l1;
        }else if(l1.val <= l2.val){
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        }else{
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }
}

提交問題:

感覺遞歸算法總是寫的時候沒有頭緒,也知道是自己調用自己,但是總是想不好。

3、迭代

迭代法就有點像我的第二種想法,就是l1不動,把l2的元素依次插入

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode Prehead = new ListNode(-1);    //設置頭節點,用來最後返回
        ListNode pre = Prehead;     //新鏈表的指針
        
        while(l1 != null && l2 != null){    //注意,這裏用的是並且,也就是說只要有一個是空了就跳出while循環
            if(l1.val <= l2.val){
                pre.next = l1;
                l1 = l1.next;
                pre = pre.next;
            }else{
                pre.next = l2;
                l2 = l2.next;
                pre = pre.next;
            }
        }
        
        pre.next = l1 == null ? l2 : l1;    //這個是跟前面的while裏的判斷呼應,這裏就把while裏還剩下的加入鏈表
        return Prehead.next;    //注意這個不能返回他本身,因爲第一個是自己構造出來的
    }
}

提交問題:

1、少了pre指針向後挪動的操作

總結:使用迭代的方法,有幾個步驟的處理感覺很巧妙

1、while循環裏只要有人是null,就跳出循環。然後在後面把不是null的都放到鏈表的後面。這樣做的一大好處是省去了while裏面複雜的判斷,完美的解決了這樣的問題。

2、還有就是最後的返回指針,這個比我自己做的要好。不會說先進行一個新的,再開始其他的。

 

 

 

 

 

 

 

 

 

 

 

 

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