给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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
- 题目数据保证列表表示的数字不含前导零
进阶:你可以想出一个时间复杂度小于 O(n2)
的算法吗?
代码(C++)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *head = nullptr, *tail = nullptr; // 初始化结果链表的头和尾
int carry = 0; // 初始化进位为 0
while (l1 || l2) { // 当 l1 或 l2 还有节点时
int n1 = l1 ? l1->val : 0; // 取 l1 当前节点的值,如果 l1 为空则取 0
int n2 = l2 ? l2->val : 0; // 取 l2 当前节点的值,如果 l2 为空则取 0
int sum = n1 + n2 + carry; // 计算当前位的和
if (!head) { // 如果结果链表为空
head = tail = new ListNode(sum % 10); // 创建头节点
} else { // 如果结果链表不为空
tail->next = new ListNode(sum % 10); // 在尾部添加新节点
tail = tail->next; // 更新尾指针
}
carry = sum / 10; // 计算进位
if (l1) l1 = l1->next; // 移动 l1 到下一个节点
if (l2) l2 = l2->next; // 移动 l2 到下一个节点
}
if (carry > 0) { // 如果最后还有进位
tail->next = new ListNode(carry); // 在尾部添加一个新节点
}
return head; // 返回结果链表的头节点
}
};
执行过程分析
初始状态
-
l1 = 2 -> 4 -> 3
(表示数字 342) -
l2 = 5 -> 6 -> 4
(表示数字 465) -
head = nullptr
,tail = nullptr
,carry = 0
第一次循环
-
取值:
-
n1 = l1->val = 2
-
n2 = l2->val = 5
-
-
计算和:
-
sum = n1 + n2 + carry = 2 + 5 + 0 = 7
-
-
创建节点:
-
sum % 10 = 7 % 10 = 7
-
因为
head
为空,创建新节点7
,head
和tail
都指向这个节点。 -
结果链表:
7
-
-
计算进位:
-
carry = sum / 10 = 7 / 10 = 0
-
-
移动指针:
-
l1 = l1->next
,l1
指向4
-
l2 = l2->next
,l2
指向6
-
第二次循环
-
取值:
-
n1 = l1->val = 4
-
n2 = l2->val = 6
-
-
计算和:
-
sum = n1 + n2 + carry = 4 + 6 + 0 = 10
-
-
创建节点:
-
sum % 10 = 10 % 10 = 0
-
因为
head
不为空,创建新节点0
,tail->next
指向这个节点,tail
更新为这个节点。 -
结果链表:
7 -> 0
-
-
计算进位:
-
carry = sum / 10 = 10 / 10 = 1
-
-
移动指针:
-
l1 = l1->next
,l1
指向3
-
l2 = l2->next
,l2
指向4
-
第三次循环
-
取值:
-
n1 = l1->val = 3
-
n2 = l2->val = 4
-
-
计算和:
-
sum = n1 + n2 + carry = 3 + 4 + 1 = 8
-
-
创建节点:
-
sum % 10 = 8 % 10 = 8
-
因为
head
不为空,创建新节点8
,tail->next
指向这个节点,tail
更新为这个节点。 -
结果链表:
7 -> 0 -> 8
-
-
计算进位:
-
carry = sum / 10 = 8 / 10 = 0
-
-
移动指针:
-
l1 = l1->next
,l1
变为nullptr
-
l2 = l2->next
,l2
变为nullptr
-
循环结束
-
l1
和l2
都为nullptr
,退出循环。 -
检查
carry
:-
carry = 0
,不需要处理进位。
-
最终结果
-
结果链表:
7 -> 0 -> 8
-
表示数字 807,即
342 + 465 = 807
。
笔记
nullptr是一个字面量,用于表示空指针。
l1->val表示当前结点的值。
l1 ? l1->val : 0判断语句,l1存在则为l1当前值否则为0。