原题链接🔗:两数相加
难度:中等⭐️
题目
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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
- 题目数据保证列表表示的数字不含前导零
题解
迭代法
- 题解:
LeetCode 上的 "两数相加"问题要求你设计一个算法,将两个非负整数的链表表示相加,并返回一个表示和的链表。这里的解题思路主要包括以下几个步骤:
理解问题:首先,要清楚题目要求的是两个非负整数的链表表示,即每个链表节点存储的是一个数字的某一位,链表的头节点存储的是最低位。
初始化:创建一个哑节点(dummy node),这个节点不存储有效数字,但是可以简化链表操作,因为链表的头节点可能在相加后被删除。
迭代处理:遍历两个链表,直到两个链表都到达末尾。在每一步中,取出当前两个节点的值,加上之前的进位(carry),计算出当前位的和以及新的进位。
处理进位:将当前位的和的个位数存储到新链表的下一个节点中,进位则保留下来,用于下一次迭代。
链表连接:在每次迭代中,将新计算出的节点连接到结果链表上。
处理剩余的链表:如果其中一个链表先遍历完,但另一个链表还有剩余,继续迭代直到另一个链表也遍历完。
处理最后的进位:如果最后一个节点相加后还有进位,需要在结果链表的末尾添加一个新的节点来存储这个进位。
返回结果:返回哑节点的下一个节点,即实际的结果链表的头节点。
代码实现:使用上述思路,用 C++ 或其他语言编写代码实现算法。
测试:编写测试用例,验证算法的正确性,包括但不限于两个链表长度相等、不等、含有前导零等情况。
通过这种方法,你可以有效地解决 “两数相加” 的问题,同时确保算法的鲁棒性和正确性。
- 复杂度:时间复杂度O(max(m,n)),要遍历两个链表的全部位置,而处理每个位置只需要 O(1) 的时间;空间复杂度O(1)。
- 代码过程:如demo所示。
- c++ demo:
#include <iostream>
// 定义链表节点结构体
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
// 函数用于将两个链表相加
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* dummyHead = new ListNode(0); // 创建一个哑节点,方便操作
ListNode* current = dummyHead; // 当前节点
int carry = 0; // 进位
while (l1 != nullptr || l2 != nullptr) {
int x = (l1 != nullptr) ? l1->val : 0;
int y = (l2 != nullptr) ? l2->val : 0;
int sum = carry + x + y;
carry = sum / 10; // 更新进位值
current->next = new ListNode(sum % 10); // 创建新节点,存储当前位的值
current = current->next; // 移动指针
if (l1 != nullptr) l1 = l1->next; // 移动链表指针
if (l2 != nullptr) l2 = l2->next;
}
if (carry > 0) {
current->next = new ListNode(carry); // 如果还有进位,添加新节点
}
ListNode* result = dummyHead->next; // 返回结果链表,跳过哑节点
delete dummyHead; // 删除哑节点
return result;
}
// 辅助函数,用于打印链表
void printList(ListNode* node) {
while (node != nullptr) {
std::cout << node->val << " -> ";
node = node->next;
}
std::cout << "null" << std::endl;
}
// 测试代码
int main() {
// 创建两个链表
ListNode* l1 = new ListNode(2);
l1->next = new ListNode(4);
l1->next->next = new ListNode(3);
ListNode* l2 = new ListNode(5);
l2->next = new ListNode(6);
l2->next->next = new ListNode(4);
std::cout << "List 1: ";
printList(l1);
std::cout << "List 2: ";
printList(l2);
// 相加链表
ListNode* result = addTwoNumbers(l1, l2);
std::cout << "Result: ";
printList(result);
// 释放链表内存
delete l1;
delete l2;
delete result;
return 0;
}