解题思路
我们使用变量来跟踪进位,并从包含最低有效位的表头开始模拟逐位相加的过程。
算法
就像你在纸上计算两个数字的和那样,我们首先从最低有效位也就是列表 l 1 l1 l1 和 l 2 l2 l2 的表头开始相加。由于每位数字都应当处于 0 … 9 0 \ldots 9 0…9 的范围内,我们计算两个数字的和时可能会出现 “溢出”。例如, 5 + 7 = 12 5 + 7 = 12 5+7=12。在这种情况下,我们会将当前位的数值设置为 2 2 2,并将进位 c a r r y = 1 carry = 1 carry=1 带入下一次迭代。进位 c a r r y carry carry 必定是 0 0 0 或 1 1 1,这是因为两个数字相加(考虑到进位)可能出现的最大和为 9 + 9 + 1 = 19 9 + 9 + 1 = 19 9+9+1=19。
伪代码如下:
- 将当前结点初始化为返回列表的哑结点。
- 将进位 c a r r y carry carry 初始化为 0。
- 将 p p p 和 q q q 分别初始化为列表 l 1 l1 l1 和 l 2 l2 l2 的头部。
- 遍历列表 l 1 l1 l1 和 l 2 l2 l2 直至到达它们的尾端。
- 将 x x x 设为结点 p p p 的值。如果 p p p 已经到达 l 1 l1 l1 的末尾,则将其值设置为 0 0 0。
- 将 y y y 设为结点 q q q 的值。如果 q q q 已经到达 l 2 l2 l2 的末尾,则将其值设置为 0 0 0。
- 设定 s u m = x + y + c a r r y sum = x + y + carry sum=x+y+carry。
- 更新进位的值, c a r r y = s u m / 10 carry = sum / 10 carry=sum/10。
- 创建一个数值为 ( s u m m o d 10 ) (sum \bmod 10) (summod10)的新结点,并将其设置为当前结点的下一个结点,然后将当前结点前进到下一个结点。
- 同时,将 p p p 和 q q q 前进到下一个结点。
- 检查 c a r r y = 1 carry = 1 carry=1 是否成立,如果成立,则向返回列表追加一个含有数字 1 的新结点。
- 返回哑结点的下一个结点。
代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
re = ListNode(0)
r = re
carry = 0
while (l1 or l2):
x = l1.val if l1 else 0
y = l2.val if l2 else 0
s = carry + x + y
r.next = ListNode(s % 10)
r = r.next
carry = s // 10
if l1 is not None:
l1 = l1.next
if l2 is not None:
l2 = l2.next
if carry > 0:
r.next = ListNode(1)
return re.next
复杂度分析
- 时间复杂度:
O
(
max
(
m
,
n
)
)
O(\max(m, n))
O(max(m,n)),假设
m
m
m 和
n
n
n 分别表示
l
1
l1
l1 和
l
2
l2
l2
的长度,上面的算法最多重复 max ( m , n ) \max(m, n) max(m,n) 次。 - 空间复杂度: O ( max ( m , n ) ) O(\max(m, n)) O(max(m,n)), 新列表的长度最多为 max ( m , n ) + 1 \max(m,n) +1 max(m,n)+1。