LeetCode 第 2 题「两数相加」
字数 1252 2025-10-26 05:22:27
好的,我们来看 LeetCode 第 2 题「两数相加」。
题目描述
给你两个 非空 的链表,分别表示两个非负整数。它们的每位数字都是按照 逆序 方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807,逆序存储就是 [7,0,8]
示例 2:
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
解题思路
1. 理解逆序存储的好处
数字在链表中是逆序存放的(个位在链表头部),这样我们在做加法时,可以从链表头部开始逐位相加,正好符合我们手算加法从低位到高位的顺序。
2. 模拟加法过程
加法规则:
- 从两个链表的头节点开始,将对应位置的数字相加,再加上 上一位的进位值。
- 当前位的和 =
l1.val + l2.val + carry。 - 当前位的结果值为
和 % 10,新的进位值为和 // 10。 - 将结果位的数字作为一个新节点接到结果链表的尾部。
- 然后指针
l1、l2向后移动一位。
3. 处理链表长度不同的情况
当其中一个链表已经到末尾,而另一个还有节点时,短链表的对应位视为 0。
4. 最后的进位
当两个链表都遍历完后,如果进位值 carry > 0,需要在结果链表最后添加一个值为 carry 的节点。
详细步骤
- 创建一个哑节点(dummy node)作为结果链表的头部,这样可以避免处理结果链表为空的情况。
- 初始化一个指针
curr指向哑节点,用于构建新链表。 - 初始化进位
carry = 0。 - 循环条件:
l1 不为空或l2 不为空或carry != 0。 - 在循环中:
- 取
l1的值(如果l1不为空,否则为 0)。 - 取
l2的值(如果l2不为空,否则为 0)。 - 计算当前和:
sum = val1 + val2 + carry。 - 计算新的进位:
carry = sum // 10。 - 计算当前位的结果:
digit = sum % 10。 - 创建一个新节点,值为
digit,并让curr.next指向它,然后curr移动到下一个节点。 - 如果
l1不为空,l1后移;如果l2不为空,l2后移。
- 取
- 循环结束后,返回
dummy.next(哑节点的下一个节点就是结果链表的真正头部)。
举例说明
以 l1 = [2,4,3]、l2 = [5,6,4] 为例:
- 初始:
carry = 0 - 第 1 位:2 + 5 + 0 = 7,进位 0,结果位 7
- 第 2 位:4 + 6 + 0 = 10,进位 1,结果位 0
- 第 3 位:3 + 4 + 1 = 8,进位 0,结果位 8
- 两个链表都结束,且进位为 0,停止。
结果链表为 [7,0,8],表示数字 807,符合 342 + 465 = 807。
代码框架(供你理解)
def addTwoNumbers(l1, l2):
dummy = ListNode(0)
curr = dummy
carry = 0
while l1 or l2 or carry:
val1 = l1.val if l1 else 0
val2 = l2.val if l2 else 0
total = val1 + val2 + carry
carry = total // 10
digit = total % 10
curr.next = ListNode(digit)
curr = curr.next
if l1:
l1 = l1.next
if l2:
l2 = l2.next
return dummy.next
这样,我们就完成了从题意理解到模拟步骤,再到代码实现的完整讲解。