【leecode面試題】兩數相加

題目描述

給出兩個 非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式存儲的,並且它們的每個節點只能存儲 一位 數字。

如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。

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

示例:

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

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/add-two-numbers
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

解題思路

1. 鏈表本身的Val的範圍是0到9,兩個鏈表Val相加結果可能會超過10,會產生進位(carry),這個進位要作爲鏈表下一個節點(Next)的Val處理要加的數值

2. 鏈表l1和l2長度不一定相等,有可能一個鏈表結束(Next指向Null),另一個鏈表仍然有有效節點

3. 兩個鏈表全部處理完畢可能會產生進位,所以兩個鏈表全部處理完畢後,要考慮如果產生了進位,該進位需要作爲結果鏈表的新節點

4. 兩個鏈表全部處理完畢的條件需要是 鏈表l1和l2都爲NULL,就退出golang的for處理代碼塊

 

要考慮的場景

1. 兩個鏈表都只有一個節點,但是有進位

l1: [5]

l2: [5]

進位爲1

2. 一個鏈表爲空,一個鏈表非空

l1: []

l2: [5, 7, 9]

3. l1和l2非空,長度不相等

l1: [5, 3, 8]

l2: [4, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 5, 1, 9]

 

代碼實現

package main

import (
    "fmt"
    "strconv"
)

// Definition for singly-linked list.
type ListNode struct {
    Val  int
    Next *ListNode
}

// Rule
// 1. for循環退出的條件是l1和l2都爲nil,代表兩條鏈表全部處理完畢
// 場景考慮
// 1. l1和l2全部處理完畢,但是有進位(carry=1), 需要在for循環退出後,將carry當作Val新增一個節點
// 2. l1爲空,l2非空
// 3. l1和l2非空,長度相等
// 4. l1和l2非空,長度不相等
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {

    var head, curr, node *ListNode
    var carry int

    for {
        var a, b, sum, val int

        if l1 == nil && l2 == nil {
            break
        }

        if l1 != nil {
            a = l1.Val
            l1 = l1.Next
        }

        if l2 != nil {
            b = l2.Val
            l2 = l2.Next
        }

        sum = a + b + carry
        if sum >= 10 {
            carry = 1
            val = sum % 10
        } else {
            carry = 0
            val = sum
        }

        if curr == nil {
            head = &ListNode{
                Val: 0,
            }
            node = &ListNode{
                Val: val,
            }
            head.Next = node
            curr = node
        } else {
            node = &ListNode{
                Val: val,
            }
            curr.Next = node
            curr = node
        }
    }

    // l1 and l2 all processed, but has carry(carry=1)
    if carry == 1 && curr != nil {
        node = &ListNode{
            Val: carry,
        }
        curr.Next = node
    }

    return head.Next
}

// 模擬打印鏈表
func printListNode(l *ListNode) {
    var nums []int
    for {
        if l == nil {
            break
        }
        nums = append(nums, l.Val)
        l = l.Next
    }

    fmt.Printf("ListNode=%+v\n", nums)
}

// 模擬構建數值鏈表
func buildListNode(s string) *ListNode {

    var p, n *ListNode

    for _, b := range s {
        v, err := strconv.Atoi(fmt.Sprintf("%c", b))
        if err != nil {
            return nil
        }
        if n == nil {
            l := &ListNode{
                Val: v,
            }
            n = l
            p = n
        } else {
            l := &ListNode{
                Val: v,
            }
            n.Next = l
            n = l
        }
        //fmt.Printf("%c\n", b)
    }

    return p
}

// 入口函數,各種場景測試
func main() {

    // l1 長度遠遠大於l2,且中間有進位
    l1 := buildListNode("1001000000000000000000000000001")
    l2 := buildListNode("5649")
    l := addTwoNumbers(l1, l2)
    printListNode(l)
    // 輸出結果:
    // ListNode=[6 6 4 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]

    // l1和l2長度相等,且節點運算完後有進位
    l1 = buildListNode("5")
    l2 = buildListNode("5")
    l = addTwoNumbers(l1, l2)
    printListNode(l)
    // 輸出結果:
    // ListNode=[0 1]

    // l1爲空, l2非空
    l1 = buildListNode("")
    l2 = buildListNode("5649")
    l = addTwoNumbers(l1, l2)
    printListNode(l)
    // 輸出結果:
    // ListNode=[5 6 4 9]
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章