一.问题描述
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
二.问题思路
通常,处理链表相加的问题,可以模拟竖式加法的方式,逐位相加,同时处理进位。因为链表已经是逆序存储的,所以可以直接从头节点开始相加,这样每一位对齐,方便处理 。同时,需要考虑边界情况。
具体步骤如下:
1. 创建一个哑节点(dummy node)作为结果链表的头节点前驱,便于操作。
2. 初始化当前指针指向哑节点,进位jinwei初始化为0。
3. 遍历两个链表,直到两个链表中至少一个到达链尾。
4. 每次取出两个链表当前节点的值(如果存在),加上进位jinwei,计算当前位的总和temp。
5. temp对10取余得到当前位的值,创建新节点,并连接到结果链表。
6. 计算新的进位jinwei = temp / 10。
7. 移动两个链表的指针(如果还没到末尾的话)。
8. 需要考虑的边界情况包括:
- 两个链表长度不同,例如一个链表比另一个长,这时候要继续处理较长的链表剩下的节点。
- 最后还有进位的情况,例如999 + 1 = 1000,这时候需要在结果链表中添加一个额外的节点
9.循环结束后,返回哑节点的下一个节点作为结果链表的头节点。
代码实现
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* dummy = new ListNode(0); // 创建一个哑节点作为结果链表的头节点前驱,便于操作
ListNode* curr = dummy; //当前指针curr指向dummy。
int jinwei = 0;
//处理两个链表相同长度的部分
while (l1 != NULL && l2 != NULL)
{
int temp = l1->val + l2->val + jinwei;
if (temp >= 10)
{
jinwei = temp / 10;
temp = temp % 10;
}
else
{
jinwei = 0;
}
curr->next = new ListNode(temp);
curr = curr->next;
l1 = l1->next;
l2 = l2->next;
}
//处理剩余结点和最后进位不为0的情况
ListNode* remaining = (l1 != NULL) ? l1 : l2;
while (remaining != NULL || jinwei > 0) {
int val = remaining ? remaining->val : 0;
int sum = val + jinwei;
jinwei = sum / 10;
curr->next = new ListNode(sum % 10);
curr = curr->next;
if (remaining) remaining = remaining->next;
else break; // 避免无限循环
}
return dummy->next;
}
};
时间复杂度:O(max(n, m)),n 和 m 分别为两个链表的长度。
空间复杂度:O(max(n, m)),存储结果链表。
以上代码写的有点杂乱,下面给出优化后的代码,思路相同
#include <iostream>
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode dummy(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;
}
carry = sum / 10;
curr->next = new ListNode(sum % 10);
curr = curr->next;
}
return dummy.next;
}
解释:
-
哑节点:简化链表头节点的处理,避免空指针问题。
-
循环条件:
l1 || l2 || carry
确保即使链表遍历完但仍有进位时继续处理。 -
逐位相加:每次循环计算当前位的和(包括进位),并更新进位。
-
创建新节点:将当前位的值存入新节点,并移动指针。
-
时间复杂度:O(max(n, m)),n 和 m 分别为两个链表的长度。
-
空间复杂度:O(max(n, m)),存储结果链表。