两数相加-单链表
- 问题描述
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/add-two-numbers
著作权归领扣网络所有。
- 解题思路
如果为了加法再度开辟一个链表空间属实有些浪费资源,并且这一题对于l1
和l2
都没有重复利用的需求。所以我选择直接对链表长度较“长”的链表进行修改
- 计算出两个链表的长度
lshort
指向短链表
lsum
指向长链表 - 利用
for
循环对长链表进行修改- 新增变量
tag
为bool
型变量,记录我们是否要进位
val_sum
为int
型变量,记录两数相加后的结果 - 对于进位之后的特殊情况
【9999999+9999= [1]0009998】
其中方括号圈起来的1
时我们长链表9999999
由于进位多出来的位置。
此时我们需要new ListNode(val_sum/10)
创建一个新的节点【❗️注意模板代码里有构造函数!】,
让lsum->next
指向该节点!【其实就相当于尾部接上一个节点】
⭕️指完之后记得break
出for
循环!!
❓why?为什么要break?
因为我们创建好节点之后,lsum
指向的并不是nullptr
!!所以for
循环会在进行一次加法,这个加法进行了tag
验证,导致进位+1
,还将我们新创建的节点里的1
也加进来了!
对于任意两个数的加法运算,其长度绝对不会超过最长的那个数字的长度+1
,间接预示着,我们至多只要建一个节点! - 返回值
return
最后我们返回的就是lsum
所指向的长链表表头即可!!!
- 新增变量
- 计算出两个链表的长度
- 代码详情
下面是我呕心沥血写出来的(大脑生锈版)代码。
/**
* 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:
int length(ListNode* l1){
int len1=0;
while(l1!=nullptr){
len1++;
l1=l1->next;
}
return len1;
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
//这是防止特殊情况【0+0=0】
if(l1->next==nullptr && l2->next==nullptr && l1->val==0 && l2->val==0){
return l1;
}
int len1=length(l1),len2=length(l2);
//找最长的那个链表当作 我们要修改的链表
ListNode *lshort=(len1>=len2?l2:l1);
ListNode *lsum=(len1>=len2?l1:l2);
int val_sum=0;bool tag=false;
for(;lsum!=nullptr;){
val_sum=0;
if(tag){
val_sum+=1;
tag=false;
}
if(lshort!=nullptr){
val_sum+=lshort->val;
lshort=lshort->next;
}
val_sum+=lsum->val;
if(val_sum>=10){
tag=true;
}
//取余数
lsum->val=val_sum%10;
//下一个要进位,但是她空值
if(tag && lsum->next==nullptr){
lsum->next=new ListNode(val_sum/10);
lsum=lsum->next;
break;
}
else{
lsum=lsum->next;
}
}
return (len1>=len2)?l1:l2;
}
};