合併兩個有序連結串列
阿新 • • 發佈:2020-10-08
1.問題描述
將兩個升序連結串列合併為一個新的 升序 連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。
示例:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4
2.求解
迭代
- 設定啞節點dummy,便於我們返回連結串列
- 當l1和l2非空時,遍歷l1、l2連結串列,比較他們的值,將dummy的next指向值較小的節點,並將較小值節點指向下一個節點
- 當遍歷完成時,判斷l1、l2是否仍然非空,將dummy指向非空節點
程式碼如下
/* 執行用時:0 ms, 在所有 Java 提交中擊敗了100.00% 的使用者 記憶體消耗:38.3 MB, 在所有 Java 提交中擊敗了89.31% 的使用者 */ public ListNode mergeTwoLists(ListNode l1, ListNode l2) { ListNode l3 = new ListNode(0); ListNode dummy = l3; while (l1 != null && l2 != null) { if (l1.val < l2.val) { l3.next = l1; l1 = l1.next; } else { l3.next = l2; l2 = l2.next; } l3 = l3.next; } if (l1 != null) { l3.next = l1; } else { l3.next = l2; } return dummy.next; }
- 時間複雜度O(m + n),m、n分別是兩個連結串列長度,至多每個節點都會呼叫一次
- 空間複雜度O(1),只使用了常數級的空間
遞迴
- 遞:每次深入是值較小的節點
- 歸:當遇到一個節點為null時,開始返回
程式碼如下
/* 執行用時:0 ms, 在所有 Java 提交中擊敗了100.00% 的使用者 記憶體消耗:38.4 MB, 在所有 Java 提交中擊敗了76.99% 的使用者 */ public ListNode mergeTwoLists(ListNode l1, ListNode l2) { return access(l1, l2); } public ListNode access(ListNode l1, ListNode l2) { if (l1 == null) { return l2; } if (l2 == null) { return l1; } if (l1.val < l2.val) { l1.next = access(l1.next, l2); return l1; } else { l2.next = access(l1, l2.next); return l2; } }
- 時間複雜度O(m + n),m、n分別是兩個連結串列長度,至多每個節點都會呼叫一次
- 空間複雜度O(m + n),每次呼叫方法都會消耗棧空間,棧空間的大小取決於遞迴的深度,最多遞迴m + n次
ps:遞迴的空間複雜度不一定都是呼叫方法的次數,若函式在尾位置呼叫自身(或是一個尾呼叫本身的其他函式等等),則稱這種情況就是尾遞迴。java語言對尾遞迴進行了優化,尾遞迴佔用的棧空間是常數級的(能優化成尾遞迴說明可以寫成迭代)