1. 程式人生 > >【LeetCode題解】2_兩數相加

【LeetCode題解】2_兩數相加

2_兩數相加

描述

給定兩個非空連結串列來表示兩個非負整數。位數按照逆序方式儲存,它們的每個節點只儲存單個數字。將兩數相加返回一個新的連結串列。

你可以假設除了數字 0 之外,這兩個數字都不會以零開頭。

示例:

輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807

解法:小學數學

思路

這道題的求解思路和在紙上求兩數之和一樣,從最低位(連結串列表頭)開始,逐位(節點)求和,用變數 carry 儲存前一位的進位結果,如果求和的過程到達長度較短的連結串列的尾部(空節點 null),則求和時將該節點的值當作 0,求和結束後還需要判斷 carry

變數的值是否為 1,如果為 1 還需要新增一個節點(節點取值為 1)作為最高位。具體的求解過程如下圖所示:

非遞迴實現

Java 實現(非遞迴寫法 1)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2)
{ ListNode dummyHead = new ListNode(-1); ListNode curNode = dummyHead, p = l1, q = l2; int carry = 0; while (p != null || q != null) { int x = (p != null) ? p.val : 0; int y = (q != null) ? q.val : 0; int sum = x + y + carry; carry =
sum / 10; curNode.next = new ListNode(sum % 10); curNode = curNode.next; if (p != null) { p = p.next; } if (q != null) { q = q.next; } } if (carry > 0) { curNode.next = new ListNode(carry); } return dummyHead.next; } }

複雜度分析:

  • 時間複雜度:O(max(m,n))O(max(m, n)),其中 mmnn 分別表示兩個連結串列的長度
  • 空間複雜度:O(max(m,n))O(max(m, n)),返回連結串列的長度最多為 max(m,n)+1max(m, n) + 1

Java 實現(非遞迴寫法 2)★

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
        
        int carry = 0;
        for (ListNode p1 = l1, p2 = l2; p1 != null || p2 != null; ) {
            int sum = carry;
            sum += (p1 != null) ? p1.val : 0;
            sum += (p2 != null) ? p2.val : 0;
            
            tail.next = new ListNode(sum % 10);
            tail = tail.next;
            
            carry = sum / 10;
            p1 = (p1 == null) ? p1 : p1.next;
            p2 = (p2 == null) ? p2 : p2.next;
        }
        
        if (carry != 0) {
            tail.next = new ListNode(carry);
        }
        return dummy.next;
    }
}

複雜度分析同上。

Python 實現

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        dummy_head = ListNode(-1)
        cur = dummy_head
        carry = 0
        
        while l1 or l2 or carry:
            v1 = v2 = 0
            if l1:
                v1 = l1.val
                l1 = l1.next
            if l2:
                v2 = l2.val
                l2 = l2.next
            carry, val = divmod(v1 + v2 + carry, 10)
            cur.next = ListNode(val)
            cur = cur.next
        return dummy_head.next

複雜度分析同上。

遞迴實現

Java 實現

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        return addTwoNumbers(l1, l2, 0);
    }

    private ListNode addTwoNumbers(ListNode l1, ListNode l2, int carry) {
        // Recursive termination condition
        if (l1 == null && l2 == null) {
            return carry > 0 ? new ListNode(carry) : null;
        }

        int sum = carry;
        ListNode l1Next = null, l2Next = null;
        if (l1 != null) {
            sum += l1.val;
            l1Next = l1.next;
        }
        if (l2 != null) {
            sum += l2.val;
            l2Next = l2.next;
        }
        ListNode curr = new ListNode(sum % 10);
        curr.next = addTwoNumbers(l1Next, l2Next, sum / 10);
        return curr;
    }
}

複雜度分析:

  • 時間複雜度:O(max(m,n))O(max(m, n)),其中 mmnn 分別表示兩個連結串列的長度
  • 空間複雜度:O(max(m,n))O(max(m, n)),額外空間是由於遞迴呼叫佔用系統棧的空間,遞迴的深度最多為 max(m,n)+1max(m, n) + 1

Python 實現

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        def helper(l1, l2, carry):
            if not l1 and not l2:
                if carry > 0:
                    return ListNode(carry)
                else:
                    return None
                
            sum = carry
            l1_next, l2_next = None, None
            if l1:
                sum += l1.val
                l1_next = l1.next
            if l2:
                sum += l2.val
                l2_next = l2.next
            curr = ListNode(sum % 10)
            curr.next = helper(l1_next, l2_next, sum // 10)
            return curr
        
        return helper(l1, l2, 0)

複雜度分析同上。