目錄
21_合併兩個有序鏈表
描述
將兩個有序鏈表合併爲一個新的有序鏈表並返回。新鏈表是通過拼接給定的兩個鏈表的所有節點組成的。
示例:
輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4
解法一:迭代
思路
因爲兩個鏈表都是有序鏈表(遞增),因此可以很容易地找出兩個鏈表中的最小元素,即比較兩個鏈表表頭的元素,時間複雜度是 \(O(1)\) 的。我們可以利用兩個指針——指向兩個鏈表的最小節點,每次比較兩個指針所指向節點的值,將值比較小的節點加到新的鏈表中,然後更新指針,如此循環往復直到到達一個鏈表的尾部。最後,還需要將另一個鏈表的剩餘部分(如果存在的話)添加到新的鏈表的尾部。
Java 實現
/**
* 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 dummyHead = new ListNode(0);
ListNode lastNode = dummyHead;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
lastNode.next = l1;
l1 = l1.next;
} else {
lastNode.next = l2;
l2 = l2.next;
}
lastNode = lastNode.next;
}
lastNode.next = l1 != null ? l1 : l2;
return dummyHead.next;
}
}
// Runtime: 9 ms
// Your runtime beats 86.44 % of java submissions.
複雜度分析:
- 時間複雜度:\(O(m+n)\),其中,\(m\) 爲鏈表 1 的節點數,\(n\) 爲鏈表 2 的節點數,算法需要遍歷兩個鏈表的所有元素
- 空間複雜度:\(O(1)\),只需要保存兩個引用
Python 實現
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
dummy_head = last_node = ListNode(0)
while l1 and l2:
if l1.val < l2.val:
last_node.next = l1
l1 = l1.next
else:
last_node.next = l2
l2 = l2.next
last_node = last_node.next
last_node.next = l1 or l2
return dummy_head.next
# Runtime: 44 ms
# Your runtime beats 99.24 % of python3 submissions.
複雜度分析同上。
解法二:遞歸
思路
遞歸的思路和迭代的思路是相同的,都是每次比較兩個鏈表的最小節點,然後對值更小的節點進行操作。不同的是,迭代是從值比較小的節點開始組建新的鏈表,而遞歸則是從值比較大的節點開始組建新的鏈表——遞歸到其中一個鏈表的尾部纔開始組建新的鏈表。
Java 實現
/**
* 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 l1 != null ? l1 : l2;
}
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next, l2);
return l1;
} else {
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
}
// Runtime: 8 ms
// Your runtime beats 99.96 % of java submissions.
複雜度分析:
- 時間複雜度:\(O(m+n)\),其中,\(m\) 爲鏈表 1 的節點數,\(n\) 爲鏈表 2 的節點數,算法需要遍歷兩個鏈表的所有元素
- 空間複雜度:\(O(m+n)\),額外的空間是由於遞歸調用佔用系統棧的空間,遞歸的深度最多爲 \(m+n\) 層
Python 實現
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if not l1 or not l2:
return l1 or l2
if l1.val < l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2
複雜度分析同上。