LeetCode两数相加

问题描述

给你两个非空的链表,表示两个非负的整数。它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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]

解题思路

这道题我自己的想法是,直接遍历两条链表,两个while循环,第一个while直接做加法,挨个做加法,因为题目给出的是条件是两个链表存储的数据是逆序,那我就直接遍历两个链表,首先根据进位标识符进行判断是否需要进位,然后根据是否需要进位从而逐个对链表的节点进行相加,如果相加后的结果需要进位,进位标识符置为1,否则为-1。第一个while循环跳出之后,第二个while循环则是链接剩下的节点与结果链表,也就是如果某个加数的长度比较长,那么高位的数据肯定需要直接链接的,所以第二个while循环就做链接操作。但此时需要注意两点:1.仍要考虑进位,因为有可能在之前的相加 操作中仍存在进位的情况,比如999+1的这种情况,所以第二个while循环仍要做进位判断;2.仍是上述情况,在最后的最高位处,999+1得到的结果是1000,结果数是要比原来两个链表都要长,所以,我们在最后需要再做一次进位标识符判断,如果此时仍有进位,那么我们就要新链接一个数据为1的节点到结果链表中。最终代码如下:

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        //数字逆序存储,那考虑尾插法存储链表,因为数字从个位开始拿,刚好逆序
        /*
            输入数据的头一个数字不能是0,也就是输入要合法,不存在高位为0的情况
            示例应该是没有头节点的但链表
            单链表肯定涉及遍历,时间复杂度为n,选择最短的链表进行遍历,直接进行相加,存储到结果链表中,
            中间使用一个进位标志符进行判断是否需要进位
        */
       ListNode *p,*q,*r,*tmp;//p,q遍历指针
       int flag = -1;//进位标志
       p = l1;
       q = l2;
    //    res = (ListNode *)malloc(sizeof(ListNode));
        ListNode *res = new ListNode();
       r = res;
       while (p!=NULL && q!=NULL)//当两个链表都没有到最末尾的时候
       {
            // tmp = (ListNode *)malloc(sizeof(ListNode));//存放结果
            ListNode *tmp = new ListNode();
            if(flag==1)
            {
                if(p->val+q->val+1 == 10)
                {
                    tmp->val=0;
                    r->next = tmp;
                    r=r->next;
                    flag=1;
                }
                else if(p->val+q->val+1>10)
                {
                    tmp->val=p->val+q->val+1-10;
                    r->next = tmp;
                    r=r->next;
                    flag=1;
                }
                else if(p->val+q->val+1<10)
                {
                    tmp->val=p->val+q->val+1;
                    r->next = tmp;
                    r=r->next;
                    flag=-1;//进位重置
                }
            }
            else//不需要进位的时候
            {
                if(p->val+q->val == 10)
                {
                    tmp->val=0;
                    r->next = tmp;
                    r=r->next;
                    flag=1;
                }
                else if(p->val+q->val>10)
                {
                    tmp->val=p->val+q->val-10;
                    r->next = tmp;
                    r=r->next;
                    flag=1;
                }
                else if(p->val+q->val<10)
                {
                    tmp->val=p->val+q->val;
                    r->next = tmp;
                    r=r->next;
                    flag=-1;//进位重置
                }
            }
            q=q->next;
            p=p->next;
       }
       while (q!=NULL||p!=NULL)//任意一个链表还没有遍历完成
       {
            // tmp = (ListNode *)malloc(sizeof(ListNode));//存放结果
            ListNode *tmp = new ListNode();
            if(q!=NULL)
            {
                if(flag==1)//此时有进位的话
                {
                    if(q->val+1==10)
                    {
                        tmp->val = 0;
                        r->next = tmp;
                        r=r->next;
                        flag=1;
                    }
                    else{
                        tmp->val = q->val+1;
                        r->next = tmp;
                        r=r->next;
                        flag=-1;
                    }
                }
                else
                {
                    tmp->val = q->val;
                    r->next = tmp;
                    r=r->next;
                }
                q=q->next;
            }
            else if(p!=NULL)
            {
                if(flag==1)//此时有进位的话
                {
                    if(p->val+1==10)
                    {
                        tmp->val = 0;
                        r->next = tmp;
                        r=r->next;
                        flag=1;
                    }
                    else{
                        tmp->val = p->val+1;
                        r->next = tmp;
                        r=r->next;
                        flag=-1;
                    }
                }
                else
                {
                    tmp->val = p->val;
                    r->next = tmp;
                    r=r->next;
                }
                p=p->next;
            }
       }
       if(flag==1)//此时还有进位的话,也就是比如999+1这种情况,就要在结果链表中再多一个节点
       {
           tmp = new ListNode();
           tmp->val = 1;
           tmp->next = NULL;
           r->next = tmp;
           r=r->next;
       }
       return res->next;
    }
};

最终的提交效果其实很差,虽然通过了,但时间和空间上的开销不低,所以还可以优化。无意间看到社区有这种解法:
进行两个链表遍历的时候,他只用了一个变量进行遍历,另一个直接用的链表本身进行遍历,这样就减少了空间的开销,后续如果某个链表遍历完,那么直接将这两个链表合并为一个链表,这样的操作就在空间和时间上少了开销。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值