给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
示例 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
题目数据保证列表表示的数字不含前导零
题目截图
解题
法1(带注释):
法1是看着这个视频,手动敲出来的源码,以及自己加上的部分注释
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
# 首先,我们要考虑如果出现空值的情况
if l1 == None:
return l2
if l2 == None:
return l1
# 创建一个存储结果的Listnode
result = ListNode(0)
p = result
# 创建一个保存进位的变量
carry = 0
while l1 and l2:
# l1.val 与 l2.val 是指当前位的数值
# 第一次进入循环也就是l1与l2的第一位
# 也就是 l1.val=2, l2.val=5
# 如果经过l1.next,l2.next之后,l1.val=4, l2.val=6
# ListNode会存储两个值:当前值(val)、下一个值(next)
# 为了不覆盖ListNode的当前值,把两数相加的值存到next值里
# 在计算完结果以后,再把next里的值赋给当前值,所以用到p.next
# 用取余保存当前的数字
# 如果该数字小于10,则保持当前的数字
# 如果大于10,比如是12,那么保存2,接下来再考虑进位的问题
p.next = ListNode((l1.val + l2.val + carry) % 10)
# 我们用 / 做除法运算,然后返回其商的整数部分,舍掉余数
# 比如12,12除以10结果为1余2,这里carry只保存1,舍掉余数2
carry = (l1.val + l2.val + carry) // 10
# 在Listnode中刷新下一位
l1 = l1.next
l2 = l2.next
# 存储Listnode的变量也要前进一位
# 也就是前面说的,把next值赋给当前值
p = p.next
# 接下来考虑l2如果位数比l1长的情况
if l2:
while l2:
p.next = ListNode((l2.val + carry) % 10)
carry = (l2.val + carry) // 10
l2 = l2.next
p = p.next
# 接下来考虑l1如果位数比l2长的情况
if l1:
while l1:
p.next = ListNode((l1.val + carry) % 10)
carry = (l1.val + carry) // 10
l1 = l1.next
p = p.next
# 如果跑完上面的程序之后还有进位,进位必然为1,因为最大的情况就是9+9=18,进位也还是1
if carry == 1:
p.next = ListNode(1)
return result.next
为了方便看代码,记下来,再来一个删掉注释的精简版
同时print一下看看数据是怎样存储的
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 == None:
return l2
if l2 == None:
return l1
result = ListNode(0)
p = result
carry = 0
while l1 and l2:
p.next = ListNode((l1.val + l2.val + carry) % 10)
print('p1:',p)
print('result1:',result)
carry = (l1.val + l2.val + carry) // 10
l1 = l1.next
l2 = l2.next
p = p.next
print('p2:',p)
print('result2:',result)
if l2:
while l2:
p.next = ListNode((l2.val + carry) % 10)
carry = (l2.val + carry) // 10
l2 = l2.next
p = p.next
if l1:
while l1:
p.next = ListNode((l1.val + carry) % 10)
carry = (l1.val + carry) // 10
l1 = l1.next
p = p.next
if carry == 1:
p.next = ListNode(1)
print('p3:',p)
print('result3:',result)
return result.next
print的结果如下:
p1: ListNode{val: 0, next: ListNode{val: 7, next: None}}
result1: ListNode{val: 0, next: ListNode{val: 7, next: None}}
p2: ListNode{val: 7, next: None}
result2: ListNode{val: 0, next: ListNode{val: 7, next: None}}
p1: ListNode{val: 7, next: ListNode{val: 0, next: None}}
result1: ListNode{val: 0, next: ListNode{val: 7, next: ListNode{val: 0, next: None}}}
p2: ListNode{val: 0, next: None}
result2: ListNode{val: 0, next: ListNode{val: 7, next: ListNode{val: 0, next: None}}}
p1: ListNode{val: 0, next: ListNode{val: 8, next: None}}
result1: ListNode{val: 0, next: ListNode{val: 7, next: ListNode{val: 0, next: ListNode{val: 8, next: None}}}}
p2: ListNode{val: 8, next: None}
result2: ListNode{val: 0, next: ListNode{val: 7, next: ListNode{val: 0, next: ListNode{val: 8, next: None}}}}
p3: ListNode{val: 8, next: None}
result3: ListNode{val: 0, next: ListNode{val: 7, next: ListNode{val: 0, next: ListNode{val: 8, next: None}}}}
result的变化是随着ListNode的出现的,每计算一次ListNode的值,该值都会存储到result的next位置。
附上自己的画图思考,是对着print的结果画出来的,是为了弄清楚result是如何存储了最终结果
法2:
题目写着是两个非空了,法1前面判断两个链表为空的处理有点多余,但如果题目没有说非空,就要能想得到需要判断链表为空的情况
法2是在链表非空的基础上进行的
# 运行条件:链表从头遍历到位,逐位相加
# (1)需要保存进位
# (2)需要保存结果
# 结束时:
# (1)两个链表只要有一个非空就需要往后进行
# (2)\U0001f6a9如果链表遍历结束,进位不为0,需要把进位项添加在链表后面
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
head = ListNode()
cur = head
values, up = 0, 0
while l1 or l2:
if not l1:
values = l2.val + up
l2 = l2.next
elif not l2:
values = l1.val + up
l1 = l1.next
else:
values = l1.val + l2.val + up
l1 = l1.next
l2 = l2.next
values, up = values % 10, values // 10
cur.next = ListNode(values)
cur = cur.next
if up:
cur.next = ListNode(up)
return head.next