Medium
题目描述
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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,需要向下一位进位
- 长度不等:当一个链表遍历完后,另一个链表可能还有剩余节点,需要继续处理
- 最后进位:所有节点处理完后,如果还有进位,需要新增一个节点
具体步骤:
- 使用一个变量
carry记录进位,初始为0 - 同时遍历两个链表,计算当前位的和:
sum = val1 + val2 + carry - 新节点的值为
sum % 10,新的进位为sum / 10 - 当其中一个链表为空时,将另一个链表的值作为当前位的值
- 最后如果还有进位,需要创建新节点
这种方法只需要一次遍历,时间复杂度为O(max(m,n)),空间复杂度为O(max(m,n))(用于存储结果)。
代码实现
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* dummy = new ListNode(0);
ListNode* curr = dummy;
int carry = 0;
while (l1 || l2 || carry) {
int sum = carry;
if (l1) {
sum += l1->val;
l1 = l1->next;
}
if (l2) {
sum += l2->val;
l2 = l2->next;
}
curr->next = new ListNode(sum % 10);
curr = curr->next;
carry = sum / 10;
}
return dummy->next;
}
};
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0)
curr = dummy
carry = 0
while l1 or l2 or carry:
sum_val = carry
if l1:
sum_val += l1.val
l1 = l1.next
if l2:
sum_val += l2.val
l2 = l2.next
curr.next = ListNode(sum_val % 10)
curr = curr.next
carry = sum_val // 10
return dummy.next
public class Solution {
public ListNode AddTwoNumbers(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode curr = dummy;
int carry = 0;
while (l1 != null || l2 != null || carry > 0) {
int sum = carry;
if (l1 != null) {
sum += l1.val;
l1 = l1.next;
}
if (l2 != null) {
sum += l2.val;
l2 = l2.next;
}
curr.next = new ListNode(sum % 10);
curr = curr.next;
carry = sum / 10;
}
return dummy.next;
}
}
var addTwoNumbers = function(l1, l2) {
let dummy = new ListNode(0);
let curr = dummy;
let carry = 0;
while (l1 || l2 || carry) {
let sum = carry;
if (l1) {
sum += l1.val;
l1 = l1.next;
}
if (l2) {
sum += l2.val;
l2 = l2.next;
}
curr.next = new ListNode(sum % 10);
curr = curr.next;
carry = Math.floor(sum / 10);
}
return dummy.next;
};
复杂度分析
| 复杂度类型 | 分析 |
|---|---|
| 时间复杂度 | O(max(m, n)),其中 m 和 n 分别是两个链表的长度 |
| 空间复杂度 | O(max(m, n)),用于存储结果链表 |
相关题目
. Multiply Strings (Medium)
. Add Binary (Easy)
. Sum of Two Integers (Medium)
. Add Strings (Easy)
. Add Two Numbers II (Medium)