1. 程式人生 > >【LeetCode題解】21_合併兩個有序連結串列

【LeetCode題解】21_合併兩個有序連結串列

21_合併兩個有序連結串列

文章目錄

描述

將兩個有序連結串列合併為一個新的有序連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。

示例:

輸入:1->2->4, 1->3->4
輸出:1->1->2->3->4->4

解法一:迭代

思路

因為兩個連結串列都是有序連結串列(遞增),因此可以很容易地找出兩個連結串列中的最小元素,即比較兩個連結串列表頭的元素,時間複雜度是 O ( 1 ) 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 ) O(m+n) ,其中, m m 為連結串列 1 的節點數, n n 為連結串列 2 的節點數,演算法需要遍歷兩個連結串列的所有元素
  • 空間複雜度: O ( 1 ) 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 ) O(m+n) ,其中, m m 為連結串列 1 的節點數, n n 為連結串列 2 的節點數,演算法需要遍歷兩個連結串列的所有元素
  • 空間複雜度: O ( m + n ) O(m+n) ,額外的空間是由於遞迴呼叫佔用系統棧的空間,遞迴的深度最多為 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

複雜度分析同上。