一、概述
按位做加法。
二、分析
1、我的方法
其实不错。时间复杂度和空间复杂度都挺好。唯一的缺点就是太繁琐了。人家十几行,我一百行,心态爆炸。
主要思路就是用一个vector保存结果,先对应位相加,加完之后把没加完的那个数字接在后面。
要注意两点,一个是普通进位,一个是最后尾巴的进位。
普通进位就是两个对应位相加超过九,则进位位置一;
如下:
while(l1!=NULL&&l2!=NULL)
{
int addon=l1->val+l2->val+add;
if(addon>9)
{
add=1;
temp.push_back(addon-10);
}
else
{
add=0;
temp.push_back(addon);
}
l1=l1->next;
l2=l2->next;
}
尾巴进位有两处,其一是较短的链表加完了,其二是较长的链表加完了,如下:
if(l1==NULL&&l2!=NULL)
{
while(l2!=NULL)
{
if(add!=0)
{
int a=l2->val+add;
if(a>9)
{
temp.push_back(a-10);
add=1;
}
else
{
temp.push_back(a);
add=0;
}
}
else
temp.push_back(l2->val);
l2=l2->next;
}
if(add!=0)
temp.push_back(add);
}
else if(l2==NULL&&l1!=NULL)
{
while(l1!=NULL)
{
if(add!=0)
{
int a=l1->val+add;
if(a>9)
{
temp.push_back(a-10);
add=1;
}
else
{
temp.push_back(a);
add=0;
}
}
else
temp.push_back(l1->val);
l1=l1->next;
}
if(add!=0)
temp.push_back(add);
}
else if(add!=0)
temp.push_back(add);
第二种容易忘了,于是会出现99+1=00的情况。
然后删去前导零即可。
2、时空复杂度均优化的方法
使用l1存储最终的结果。以此来使空间复杂度由O(n)变为O(1)。
核心代码为
l1->val+=carry+(l2!=NULL?l2->val:0);
l1的对应位的结果为l1的原值加上l2的对应位加上进位值,若l2不为NULL;或者为l1的原值加上0加上进位值,若l2为NULL。
这样就不需要考虑尾巴进位的特殊情况了。
例如99+1,首先9+1,对应位为0,进位1,然后l2为NULL,l1的9加上0加上进位的1,仍为0,再加尾巴即可。
若l2比l1长,那么:首先把l2接在l1后面,然后令l2为NULL。
例如1+99,首先1+9,对应位为0,进位1,然后把9接在l1后面,l1为09,然后l1的9加上0加上进位的1,仍为0,再加尾巴。
为了让代码行数尽可能少,我们要把特殊情况一般化。
有几个地方需要注意,见代码:
while(l1!=NULL)
{
l1->val+=carry+(l2!=NULL?l2->val:0);
carry=l1->val/10;
l1->val%=10;
if(l1->next==NULL&&l2!=NULL)
{
l1->next=l2->next;
l2=NULL;
}
if(l1->next==NULL&&carry!=0)
{
l1->next=new ListNode(carry);
l1=l1->next;
}
l1=l1->next;
if(l2!=NULL)
l2=l2->next;
}
要先计算carry再计算l1->val,而不能反过来。
第一个if的判断应该是l2而不是l2->next,同时注意在接完之后令l2为NULL。
第二个if在接尾巴之后要向下走一个,否则会出错。
三、总结
若想优化空间复杂度,一般直接在输入上修改,若想让代码行数变短,要将特殊情况一般化,当然这有点难。
PS:代码如下:
1、我的代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int add=0;
vector<int> temp;
while(l1!=NULL&&l2!=NULL)
{
int addon=l1->val+l2->val+add;
if(addon>9)
{
add=1;
temp.push_back(addon-10);
}
else
{
add=0;
temp.push_back(addon);
}
l1=l1->next;
l2=l2->next;
}
if(l1==NULL&&l2!=NULL)
{
while(l2!=NULL)
{
if(add!=0)
{
int a=l2->val+add;
if(a>9)
{
temp.push_back(a-10);
add=1;
}
else
{
temp.push_back(a);
add=0;
}
}
else
temp.push_back(l2->val);
l2=l2->next;
}
if(add!=0)
temp.push_back(add);
}
else if(l2==NULL&&l1!=NULL)
{
while(l1!=NULL)
{
if(add!=0)
{
int a=l1->val+add;
if(a>9)
{
temp.push_back(a-10);
add=1;
}
else
{
temp.push_back(a);
add=0;
}
}
else
temp.push_back(l1->val);
l1=l1->next;
}
if(add!=0)
temp.push_back(add);
}
else if(add!=0)
temp.push_back(add);
vector<int>::reverse_iterator it;
for(it=temp.rbegin();it!=temp.rend();it++)
if(*it==0)
temp.pop_back();
else
break;
if(temp.size()==0)
{
ListNode* ans=new ListNode(0);
return ans;
}
ListNode* ans=new ListNode(temp[0]);
ListNode* pointer=ans;
for(int i=1;i<temp.size();i++)
{
ListNode* a=new ListNode(temp[i]);
pointer->next=a;
pointer=a;
}
return ans;
}
};
2、较好代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode* head=l1;
int carry=0;
while(l1!=NULL)
{
l1->val+=carry+(l2!=NULL?l2->val:0);
carry=l1->val/10;
l1->val%=10;
if(l1->next==NULL&&l2!=NULL)
{
l1->next=l2->next;
l2=NULL;
}
if(l1->next==NULL&&carry!=0)
{
l1->next=new ListNode(carry);
l1=l1->next;
}
l1=l1->next;
if(l2!=NULL)
l2=l2->next;
}
return head;
}
};