两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
思考
这题比较方便的是给定的两个链表已经是从个位开始的,不需要我们再去找到最低位。 有两个需要注意的地方:
- 第一个是长短不一的链表是要一直处理到最长那个结束的,而不是最短链表
- 第二个需要注意的地方是最高位之和可能会导致进位,此时可能需要新增一个节点,如 753+864 中 7+8导致的进位
解答
- 时间复杂度: O(max(list1, list2)),因为处理的次数取决于最长的那个链表
- 空间复杂度: O(max(list1, list2)),新列表的长度最多为max(list1, list2)+1,因为最高位可能导致进位
package algo
type ListNode struct {
Val int
Next *ListNode
}
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
// 存在一个空list时无意义
if l1 == nil || l2 == nil {
return nil
}
var (
sumList = &ListNode{}
currentNode = sumList
nextL1 = l1
nextL2 = l2
carry = 0 //进位值
)
for nextL1 != nil || nextL2 != nil {
var sum, x, y int
if nextL1 != nil {
x = nextL1.Val
nextL1 = nextL1.Next
} else {
x = 0
}
if nextL2 != nil {
y = nextL2.Val
nextL2 = nextL2.Next
} else {
y = 0
}
sum = x + y + carry
carry = sum / 10
// 不要使用 currentNode.Val = sum % 10; currentNode.Next = &ListNode{};
// 否则会导致最后多余一个ListNode{}结点
currentNode.Next = &ListNode{Val: sum % 10}
currentNode = currentNode.Next
}
// 最高位相加导致的进位,如 753+864 中 7+8导致的进位
if carry > 0 {
currentNode.Next = &ListNode{Val: carry}
}
return sumList.Next
}
单元测试:
package algo
import (
"math/rand"
"strings"
"testing"
)
func TestTwoNumbers(t *testing.T) {
linkList1 := makeList()
linkList2 := makeList()
res := addTwoNumbers(linkList1, linkList2)
if res == nil {
t.Fatal("empty result")
}
print("第一链表: ")
traverse(linkList1)
print("第二链表: ")
traverse(linkList2)
print("结果链表: ")
traverse(res)
println(strings.Repeat("=", 30))
sameList := makeList()
res = addTwoNumbers(sameList, sameList)
if res == nil {
t.Fatal("empty result")
}
print("同一链表: ")
traverse(sameList)
print("结果链表: ")
traverse(res)
}
// 创建单链表
func makeList() *ListNode {
var listNode = &ListNode{Val: rand.Intn(9) + 1}
cnt := rand.Intn(6) + 3
for i := 1; i < cnt; i++ {
l := listNode
for {
if l.Next == nil {
l.Next = &ListNode{Val: rand.Intn(9) + 1}
break
}
l = l.Next
}
}
return listNode
}
// 遍历单链表
func traverse(linkList *ListNode) {
iter := linkList
for {
if iter != nil {
if iter.Next == nil {
print(iter.Val)
} else {
print(iter.Val, "->")
}
iter = iter.Next
} else {
break
}
}
println()
}