題目描述
給出兩個 非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式存儲的,並且它們的每個節點只能存儲 一位 數字。
如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。
您可以假設除了數字 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]
}