【LeetCode】2. Add Two Numbers 链表

本文对比两种链表加法实现方案,一种繁琐但直观,另一种通过直接修改输入链表达到空间复杂度O(1)的效果,并减少代码量。讨论了普通进位与尾巴进位的处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概述

按位做加法。

二、分析

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;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值