题目
\quad \quad 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
一、所需知识
- ListCode 链表
ListCode是一个链表结构。它由 当前节点数据+指向下一个节点数据的指针组成。如下图
基于此, 节点ListCode
的结构定义:
(需要具备两个基本属性:一个是当前节点的值,一个是下一个节点的ListNode类型的值。)
#include
struct ListNode
{
// 两个基本属性
int val; // 当前节点的数据
ListNode *next; // 下一个节点的地址
// 还可以加上 构造函数
ListNode() : val(0), next(nullptr) {} // 设置当前节点的值为 0,下一个节点的地址为空。
ListNode(int x) : val(x), next(nullptr) {} // 将x的值赋给当前节点,下一个节点地址为空。
ListNode(int x, ListNode *next) : val(x), next(next) {} // // 将x的值赋给当前节点,下一个节点地址为next。
};
// 假如说要定义[2, 4, 6]这么一个链表,也可以这么赋值,这样我感觉会更清晰的理解到链表的结构。
ListNode l1 = new ListNode(2, new ListNode(4, new ListNode(6)));
- NULL、nullptr 、0 的区别
二、解题
代码如下(力扣LeetCode):
class Solution {
public:
ListNode* addTwoNumbers(ListNode* Nl1, ListNode* Nl2)
{
// 首先定义两个链表,分别存放 链表头部信息(为了防止在循环赋值中丢失前面的头部信息) 与 在循环相加连表示动态赋值的链表。
ListNode* curr = nullptr; // 循环中动态赋值的链表
ListNode* head = nullptr; // 存放链表头节点信息
// 两个链表直接相加,得出来的数是不对的。因为讯在满十进位的问题。因此用 %10 得出本节点的数, 用 /10 得出进位数。 如果最后一个节点 对应相加 发现进位数。需要在链表尾部追加一个节点寻访进位数。
int temp = 0; // 初始的进位数
// 循环遍历需要相加的两个链表, 获取相应的值
while (Nl1 != nullptr || Nl2 != nullptr)
{
// 取值 判断当前节点的值是否为空 如果为空 就给当前节点赋值(防止两个链表长度不一致,就给缺少的数赋值为0)
int num1 = Nl1 ? Nl1->val : 0;
int num2 = Nl2 ? Nl2->val : 0;
int sum = num1 + num2 + temp; //对应节点值相加以及加上上一次计算的进位数
temp = sum / 10; // 本次计算的进位数
int val0 = sum % 10; // 本次计算的节点值
// 给链表赋值。 并判断链表头部是否为空
// 第一次存放时候 就是
if (curr == nullptr)
{
// 先给curr链表赋值 进行动态更行
curr = new ListNode(val0);
// 把链表头节点值 存放在 head 链表中,后续curr指向next节点重置节点信息时,head不会被重置
head = curr;
}
else
{
// 头部不为空 指定 next 节点
curr->next = new ListNode(val0);
// curr链表向后移, 为下一次循环继续给next节点赋值
curr = curr->next;
}
// l1 和 l2 链表向后移 获取下一个节点信息
if (Nl1 != nullptr)
{
Nl1 = Nl1->next;
}
if (Nl2 != nullptr)
{
Nl2 = Nl2->next;
}
}
// 判断最后一位进位数
if (temp > 0)
curr->next = new ListNode(temp);
return head;
}
};
结果如下:
三、扩展
代码如下(Visual Studio):自己输入两个目标数据集,然后返回数据集中元素个数,最后在进行累和。
#include <iostream>
using namespace std;
struct ListNode {
int val; // 当前节点的数据
ListNode *next; // 下一个节点的地址
ListNode() : val(0), next(nullptr) {} // 设置当前节点的值为 0,下一个节点的地址为空。
ListNode(int x) : val(x), next(nullptr) {} // 将x的值赋给当前节点,下一个节点地址为空。
ListNode(int x, ListNode *next) : val(x), next(next) {} // // 将x的值赋给当前节点,下一个节点地址为next。
};
class Solution {
public:
ListNode* addTwoNumbers(ListNode* Nl1, ListNode* Nl2)
{
// 首先定义两个链表,分别存放 链表头部信息(为了防止在循环赋值中丢失前面的头部信息) 与 在循环相加连表示动态赋值的链表。
ListNode* curr = nullptr; // 循环中动态赋值的链表
ListNode* head = nullptr; // 存放链表头节点信息
// 两个链表直接相加,得出来的数是不对的。因为讯在满十进位的问题。因此用 %10 得出本节点的数, 用 /10 得出进位数。 如果最后一个节点 对应相加 发现进位数。需要在链表尾部追加一个节点寻访进位数。
int temp = 0; // 初始的进位数
// 循环遍历需要相加的两个链表, 获取相应的值
while (Nl1 != nullptr || Nl2 != nullptr)
{
// 取值 判断当前节点的值是否为空 如果为空 就给当前节点赋值(防止两个链表长度不一致,就给缺少的数赋值为0)
int num1 = Nl1 ? Nl1->val : 0;
int num2 = Nl2 ? Nl2->val : 0;
int sum = num1 + num2 + temp; //对应节点值相加以及加上上一次计算的进位数
temp = sum / 10; // 本次计算的进位数
int val0 = sum % 10; // 本次计算的节点值
// 给链表赋值。 并判断链表头部是否为空
// 第一次存放时候 就是
if (curr == nullptr)
{
// 先给curr链表赋值 进行动态更行
curr = new ListNode(val0);
// 把链表头节点值 存放在 head 链表中,后续curr指向next节点重置节点信息时,head不会被重置
head = curr;
}
else
{
// 头部不为空 指定 next 节点
curr->next = new ListNode(val0);
// curr链表向后移, 为下一次循环继续给next节点赋值
curr = curr->next;
}
// l1 和 l2 链表向后移 获取下一个节点信息
if (Nl1 != nullptr)
{
Nl1 = Nl1->next;
}
if (Nl2 != nullptr)
{
Nl2 = Nl2->next;
}
}
// 判断最后一位进位数
if (temp > 0)
curr->next = new ListNode(temp);
return head;
}
};
// 对链表 l1 和 l2 进行赋值
ListNode* getvalue(ListNode* Lval)
{
ListNode* curr0 = nullptr;
int c;
char d;
while (cin >> c)
{
if (Lval == nullptr)
{
Lval = new ListNode(c);
curr0 = Lval;
}
else
{
Lval->next = new ListNode(c);
Lval = Lval->next;
}
if ((d = getchar()) == '\n')
break;
}
return curr0;
}
// 获取链表长度
int getlength(ListNode* L)
{
ListNode* t = nullptr;
t = L->next;
int sum = 0;
while (t)
{
sum++;
t = t->next;
}
cout << "链表的长度为(即链表节点个数为):" << sum+1 << endl;
return sum;
}
// 输出累和的链表
void printList(ListNode* head)
{
ListNode* phead = head;
cout <<"类和结果为:" << "[";
while (phead != NULL)
{
cout << phead->val << " ";
phead = phead->next;
}
cout << "]" << "\n";
}
int main()
{
Solution sol;
ListNode* ans;
ListNode* l1 = nullptr;
ListNode* l2 = nullptr;
cout << "请输入l1链表的值:" << endl;
l1 = getvalue(l1);
getlength(l1);
cout << "请输入l2链表的值:" << endl;
l2 = getvalue(l2);
getlength(l2);
ans = sol.addTwoNumbers(l1, l2);
printList(ans);
system("pause");
return 0;
}
结果如下图所示:
示例一:
示例二: