讓我們一起啃演算法----兩數相加

三斤和他的喵發表於2020-04-08

兩數相加(Add-Two-Numbers)

這是 LeetCode 的第二題,題目挺常規的,題幹如下:

給出兩個 非空 的連結串列用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式儲存的,並且它們的每個節點只能儲存 一位 數字。
如果,我們將這兩個數相加起來,則會返回一個新的連結串列來表示它們的和。
您可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。
示例:
    輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
    輸出:7 -> 0 -> 8
    原因:342 + 465 = 807

解題思路

這個題目的解法類似我們小時候算兩個多位數的加法:從低位開始相加,大於等於10時則取值的個位數,並向前進1

只不過現在多位數用連結串列來表示了並且最後的值用連結串列返回了而已。

根據上面這個思路需要注意的是進位( carry ),相加的時要加上 carry 的值。

實現流程

假設我們有兩條連結串列L1L2,並且初始化了carry為0value為0Point、Head指向一個初始結果連結串列,其中carry表示低位的進位,value表示結果連結串列尾節點的值,Ponit指向尾節點用於新增節點存放value的值,Head始終指向結果連結串列的頭節點。
程式碼實現思路我畫成了流程:從上到下,從左到右,配合程式碼一起看效果更佳喲

具體的程式碼實現

GO實現

func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
    var (
        carry        int  // 進位
        currentValue int  // 要追加節點的Val的,也就是圖中的value
        centerValue  int  // 中間值
        point        = &ListNode{}
        head         = point
    )
    for l1 != nil && l2 != nil {
        centerValue = l1.Val + l2.Val + carry
        currentValue = centerValue % 10
        carry = centerValue / 10
        // 新增一個節點,用於儲存結果
        point.Next = &ListNode{Val: currentValue}
        // point始終指向最後一個節點
        point = point.Next
        l1 = l1.Next
        l2 = l2.Next
    }

    // 上一個for迴圈執行完畢,有可能l1或者l2仍有節點,下面兩個迴圈就是處理這種情況的

    // 處理兩個連結串列長度不一致的情況
    for l1 != nil {
        centerValue = l1.Val + carry
        currentValue = centerValue % 10
        carry = centerValue / 10
        point.Next = &ListNode{Val: currentValue}
        point = point.Next
        l1 = l1.Next
    }

    // 處理兩個連結串列長度不一致的情況
    for l2 != nil {
        centerValue = l2.Val + carry
        currentValue = centerValue % 10
        carry = centerValue / 10
        point.Next = &ListNode{Val: currentValue}
        point = point.Next
        l2 = l2.Next
    }

    // 如果進位不為0,需再追加一個節點
    if carry == 1 {
        point.Next = &ListNode{Val: 1}
    }

    // 因為head指向的是初始節點,所以head.Next才是我們要的結果連結串列真正的頭節點
    return head.Next
}

其實仔細看上面的程式碼會發現有很多重複的邏輯,所以簡單做了一個優化,程式碼如下:

func addTwoNumbersOptimize(l1 *ListNode, l2 *ListNode) *ListNode {
    var (
        carry        int
        currentValue int
        centerValue  int
        point        = &ListNode{}
        head         = point
    )
    for l1 != nil || l2 != nil || carry != 0 {
        lValue := 0
        rValue := 0
        if l1 != nil {
            lValue = l1.Val
            l1 = l1.Next
        }
        if l2 != nil {
            rValue = l2.Val
            l2 = l2.Next
        }
        centerValue = lValue + rValue + carry
        currentValue = centerValue % 10
        carry = centerValue / 10
        point.Next = &ListNode{Val: currentValue}
        point = point.Next

    }
    return head.Next
}

總結

每天進步一點點,加油!
完整程式碼:https://github.com/wx-satellite/go-leetcod…

本作品採用《CC 協議》,轉載必須註明作者和本文連結

三斤

相關文章