两数相加
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 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() }