【leetcode】两数相加2

两数相加2

问题描述: 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

      1.每位相加,再加进位值,生成一个新的链表
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *h = new ListNode(0);//哑节点,用于返回结果链表
        ListNode *cur=h;//跟踪结点
        int value=0 ;//记录每位相加的结果
        int carry=0;//记录进位值
        while(l1!=NULL&&l2!=NULL)
        {
              value=l1->val+l2->val+carry;
              ListNode *temp=new ListNode(value%10);//本位结果添加到结果链表中
              cur->next=temp;       
              carry=value/10;//计算进位值
              l1=l1->next;
              l2=l2->next;
              cur=temp;
        }
        while (l2!=NULL)//对较长的链表继续进行相加操作
        {
              value=l2->val+carry;
              ListNode *temp=new ListNode(value%10);
              cur->next=temp;       
              carry=value/10;
              l2=l2->next;
              cur=temp;
        }
        while (l1!=NULL)
                 {
                    value=l1->val+carry;
                    ListNode *temp=new ListNode(value%10);
                    cur->next=temp;       
                    carry=value/10;
                    cur=temp;
                    l1=l1->next;
                 }

        if(carry==1)//计算最高位有没有进位
        {
            ListNode* n = new ListNode(1);
            cur->next = n;
        }
        return h->next;//返回结果链表,哑结点的后继结点
                      
        }
};

复杂度很高。

个人出错的地方有:
1.链表添加结点的时候必须先初始化一个结点,才能让next指向该结点,不可以直接给next的val进行赋值。即需要new listnode()。
2.需要单独返回一个链表作为结果的时候,可以借助哑节点,可以避免很多其他操作。
3.最初想的是直接进行int型数的加和,这里需要考虑溢出问题。

		2.<题解方法>在给定链表上直接进行加和,大大减少空间复杂度。

进位可以不需要进行中间结果的记录,最终的结果也不需要单独开辟新的链表。

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *s = l1;//记录初始位置
        while(l1->next != nullptr && l2->next != nullptr){//l1和l2都没耗尽前
            l1->val += l2->val;//对位相加至l1
            if (l1->val > 9){//进位
                l1->next->val += (l1->val / 10);
                l1->val = l1->val % 10;
            }
            l1 = l1->next;
            l2 = l2->next;
        }
        if(l1->next == nullptr) l1->next = l2->next;//如果l1耗尽,则将l2剩余部分接至l1后
        l1->val += l2->val;//l1和l2较短者的最后一个元素加至l1
        while(l1->next != nullptr){//l1没耗尽前
            if (l1->val > 9){//进位
                l1->next->val += (l1->val / 10);
                l1->val = l1->val % 10;
            }
            l1 = l1->next;
        }
        if (l1->val > 9){//如果最后一位大于9,建立新节点用于进位
            ListNode *app = new ListNode(l1->val / 10);

思路精妙之处:在较短的链表的最后一个元素处,进行两个链表相加时,如果用于存放结果的l1链表较短,则将除去与l1最后一个元素相加的结点外的其余链表结点与l1相连,再对l1最后一个元素进行相加,之后就是l1所有后继结点与进位值的相加。
如果是l2较短,则将l2最后一个元素与l1相加后,直接对l1剩余部分与进位值的加和。
(此题解的关键之处就在于l1怎么操作才能存放所有结点的相加和结果)

		3.递归法:由于每一位都是本位与进位的相加和结果,很容易想到递归

每位数字相加以后,得到本位和进位值,本位连接到结果链表中,进位在递归过程中进入下一轮,如果短链表所有元素已经相加完,则在接下来的加运算中该链表元素取0,直到所有的链表和进位都为null则结束。

class Solution {
public:
    int overflow;
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        if(!l1 && !l2 && !overflow) return NULL;
        int x = (l1 == NULL ? 0 : l1->val);
        int y = (l2 == NULL ? 0 : l2->val);
        int sum = x + y + overflow;
        ListNode* cur_node = new ListNode(sum % 10);
        overflow = sum / 10;
        if(l1) l1 = l1->next;
        if(l2) l2 = l2->next;
        cur_node->next = addTwoNumbers(l1, l2);
        return cur_node;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值