题目描述
给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例1
addtwonumber1.jpeg输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例2
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例3
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
提示:
- 每个链表中的节点数在范围 [1, 100] 内
- 0 <= Node.val <= 9
- 题目数据保证列表表示的数字不含前导零
思路
做题之前最重要的事情是看题目的提示,提示中会给出一些有关题目的限制条件。本题的限制条件有3个,第一个规定了链表节点数的范围,最少都是1个。节点的值在0到9之间,所以最大的两个数9+9=18,进位最多只能是1,有可能是0。题目给出的测试数据保证了不会出现前导0的情况。
这道题考察单链表的遍历操作,特别是要注意处理空指针和进位问题,最容易出错的地方时当遍历结束后,要注意如果进位为1,那么还要额外处理一下最后一个节点,别忘记了。我写的第一版算法如下:
func addTwoNumbers(l1 *ListNode, l2 *ListNode) *ListNode {
result := &ListNode{0, nil}
ptr1, ptr2, next := l1, l2, result
carry := 0
for ptr1 != nil && ptr2 != nil {
next.Val = ptr1.Val + ptr2.Val + carry
if next.Val >= 10 {
carry = 1
next.Val -= 10
} else {
carry = 0
}
ptr1 = ptr1.Next
ptr2 = ptr2.Next
if carry == 1 || ptr1 != nil || ptr2 != nil {
next.Next = &ListNode{0, nil}
next = next.Next
}
}
var ptr *ListNode
if ptr1 != nil {
ptr = ptr1
} else {
ptr = ptr2
}
if ptr == nil && carry == 1 {
next.Val += carry
if next.Val >= 10 {
next.Val -= 10
next.Next = &ListNode{1, nil}
}
} else {
for ptr != nil {
next.Val = ptr.Val + carry
if next.Val >= 10 {
carry = 1
next.Val -= 10
} else {
carry = 0
}
ptr = ptr.Next
if ptr != nil {
next.Next = &ListNode{0, nil}
next = next.Next
}
}
if carry == 1 {
next.Next = &ListNode{1, nil}
}
}
return result
}
后来看了官方题解,发现人家的方法和我一样但写的比我简洁,我就重新试着写了一下:
func addTwoNumbers(l1 *ListNode, l2 *ListNode) (result *ListNode) {
ptr1, ptr2, next := l1, l2, result
value, carry := 0, 0
for ptr1 != nil || ptr2 != nil {
sum := carry
if ptr1 != nil {
sum += ptr1.Val
ptr1 = ptr1.Next
}
if ptr2 != nil {
sum += ptr2.Val
ptr2 = ptr2.Next
}
value, carry = sum % 10, sum / 10
if result == nil {
next = &ListNode{value, nil}
result = next
} else {
next.Next = &ListNode{value, nil}
next = next.Next
}
}
if carry == 1 {
next.Next = &ListNode{carry, nil}
}
return
}
网友评论