链接:https://leetcode.cn/problems/add-two-numbers/?envType=featured-list&envId=2ckc81c?envType=featured-list&envId=2ckc81c
难度:中等
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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
遍历两个链表,然后依次取节点元素相加。如果相加大于等于10,则需要进位,把位数加到后面的和中。
两个链表的长度不一定一样。遍历时,如果短的遍历完了,相加按照0即可。
注意如果链各个链表都加完了,进位还为1,链表还有下一个节点,值为1。
还需要注意的是,在第一次循环时,我们无法往一个空节点的末尾添加节点。这里的技巧是,创建一个哨兵节点(dummy node),当成初始的「空链表」。循环结束后,哨兵节点的下一个节点就是最终要返回的链表头节点。
代码如下:
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
# cur_node是当前链表,dummy_node是哨兵节点
cur_node = dummy_node = ListNode()
# carry用来记录上次两数相加进位的数字
carry = 0
# 如果两个链表有一个不为空,或者进位的不为0,执行下面的逻辑
while l1 or l2 or carry != 0:
# 当前的和为链表两个节点数字相加,再加上上一次进位的数字,注意链表长度可能不一样,如果短的那个没有节点了,就取0即可
carry = (l1.val if l1 else 0) + (l2.val if l2 else 0) + carry
# 下一个节点的值,取和对10的余数即可
cur_node.next = ListNode(carry % 10)
# 更新当前节点为下一个节点
cur_node = cur_node.next
# 新的进位是除以10的商
carry //= 10
# 最后遍历参数链表里下一个节点
l1 = l1.next if l1 else None
l2 = l2.next if l2 else None
# 哨兵节点的下一个节点即为结果节点
return dummy_node.next
# 辅助函数:用来创建链表
def build_link(l : Optional[list]):
head = current_node = None
for ele in l:
if current_node:
current_node.next = ListNode(ele)
current_node = current_node.next
else:
head = current_node = ListNode(ele)
return head
# 辅助函数:用来打印链表
def print_node(n : Optional[ListNode]):
l = []
while n:
l.append(n.val)
n = n.next
print(l)
if __name__ == "__main__":
l1 = [9, 9, 9, 9, 9, 9, 9]
l2 = [9, 9, 9, 9]
link1 = build_link(l1)
link2 = build_link(l2)
res = Solution().addTwoNumbers(link1, link2)
print_node(res)
复杂度
时间复杂度:O(n)
空间复杂度:O(1)