leetcode_合併鏈表

方法 1:遞歸

思路

  • 首先考慮邊界情況。 特殊的,如果 l1 或者 l2 一開始就是 null ,那麼沒有任何操作需要合併,所以我們只需要返回非空鏈表。
  • 否則,我們要判斷 l1 和 l2 哪一個的頭元素更小,然後遞歸地決定下一個添加到鏈表裏的節點。如果兩個鏈表有任意一方爲空,那麼返回其中非空鏈表即可,遞歸終止
  • 代碼缺點:會破壞原來鏈表的邏輯位置,因爲是原地修改的
  • 判斷某鏈表是否爲空時,return 另一個鏈表是代表直接將該鏈表剩餘部分插入合併鏈表中
  • NOTACK 判斷兩個鏈表的節點是否相同時的return 語句,例子:l1:1->10,l2: 2->9,遞歸到基例時爲return l1(直接結束遞歸退層),此時再return l1(返回結果鏈表的指針)
    if(l1->val < l2->val){
        l1->next = mergeTwoLists(l1->next,l2);
        return l1;

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;
        }

    }
}

複雜度分析

時間複雜度:O(n+m)。 因爲每次調用遞歸都會去掉 l1 或者 l2 的遍歷到的元素(直到至少有一個鏈表爲空),函數 mergeTwoList 中只會遍歷每個元素一次。所以,時間複雜度與合併後的鏈表長度呈線性關係。

空間複雜度:O(n+m)。調用 mergeTwoLists 退出時, l1 和 l2 中每個元素都一定已經被遍歷過了,所以 n+m 個棧幀會消耗 O(n+m) 的空間。

方法 2:迭代

算法

  • 首先,我們設定一個哨兵節點 “prehead” ,讓我們比較容易地返回合併後的鏈表。
  • 我們維護一個 prev 指針,我們需要做的是調整它的 next 指針。然後,我們重複以下過程,不管我們將哪一個元素接在prev.next 後面,我們不僅要把 prev 指針向後移一個元素,兩個鏈表的數據域在比較大小後,相應的也需要將其指針向後移動
  • 在循環終止的時候, l1 和 l2 至多有一個是非空的。由於輸入的兩個鏈表都是有序的,所以不管哪個鏈表是非空的,它包含的元素都比前面已經合併鏈表中的元素都要大。so 我們需將剩下的非空鏈表接在已經合併鏈表的後即可
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // maintain an unchanging reference to node ahead of the return node.  維護一個不會改變引用的節點,做返回合併後的鏈表使用
        ListNode prehead = new ListNode(-1);

        ListNode prev = prehead;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                prev.next = l1;
                l1 = l1.next;
                
            } else {
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }

        // exactly one of l1 and l2 can be non-null at this point, so connect the non-null list to the end of the merged list.
        prev.next = l1 == null ? l2 : l1;

        return prehead.next;
    }
}

複雜度分析

時間複雜度:O(n+m) 。因爲每次循環迭代中,l1 和 l2 只有一個元素會被放進合併鏈表中, while循環的次數等於兩個鏈表的總長度。所有其他工作都是常數級別的,所以總的時間複雜度是線性的。

空間複雜度:O(1) 。迭代的過程只會產生幾個指針,所以它所需要的空間是常數級別的。??? NOT ACK 應該還申請了一個鏈表空間用來存儲合併鏈表纔對

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