leetcode 2. 两数相加

题目描述

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-two-numbers
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

在这里插入图片描述
输入: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]

解题思路

链表现在是倒序,但是我们把链表从头结点开始每一位匹配相加,正好跟我们做加法的顺序是一样的,每一次从l1,l2取出一个数,两两相加,把得到的和模10得到余数取出来作为新节点插入链表,把得到的和除以10得到进位记为flag参加下一次的运算

当两个链表的长度不一样时,从短的链表结束开始,把长的链表的剩下的元素考虑进位情况插入到新的链表中即可

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我的提交

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
       int flag=0;//进位标识符
        int l1_length=0;
        int l2_length=0;
        ListNode temp1=l1;
        ListNode temp2=l2;
        while(temp1!=null)//求链表1的长度
        {
            l1_length=l1_length+1;
            temp1=temp1.next;
        }
        while(temp2!=null)//求链表2的长度
        {
            l2_length=l2_length+1;
            temp2=temp2.next;
        }
     //先定义新链表的头结点
    ListNode head= new  ListNode ((l1.val+l2.val)%10);//取余数作为节点的值
    ListNode cur=head;//保留head,用cur代替head,后续操作cur
    flag=(l1.val+l2.val)/10;//求出进位
    l1=l1.next;
    l2=l2.next;
   
     if(l1_length==l2_length)//两个链表长度相等
     {
         while(l1!=null)
         {
             cur.next= new  ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
             flag=(l1.val+l2.val+flag)/10;//取出进位
             cur=cur.next;  //这一句我是真怕形成环,但是还好过了                                     
             l1=l1.next;
             l2=l2.next;           
         }  
        if(l1==null&&flag!=0)//考虑最后一位有进位的情况,比如[2,4,3],[5,6,8].输出[7,0,2,1]
         {
            cur.next=new ListNode(flag);
         }     
     }
     if(l1_length>l2_length)//l1链表长度大于l2链表
     {
         while(l2!=null)
         {
           cur.next=new  ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
           flag=(l1.val+l2.val+flag)/10;//取出进位
           cur=cur.next; 
           l1=l1.next;
           l2=l2.next;   
         } 
           while(l1!=null)//l2已经遍历完毕,现在考虑进位情况把l1剩下的部分插入新链表
           {
             cur.next=new ListNode((l1.val+flag)%10);
             flag=(l1.val+flag)/10;
             cur=cur.next;
             l1=l1.next;
           }  

         if(l1==null&&flag!=0)//考虑最后一位有进位的情况,比如l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]输出:[8,9,9,9,0,0,0,1]
         {
            cur.next=new ListNode(flag);
         }     
        
     }

     if(l1_length<l2_length)//l1链表长度小于l2链表
     {
        while(l1!=null)
         {
           cur.next=new  ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
           flag=(l1.val+l2.val+flag)/10;//取出进位
           cur=cur.next; 
           l1=l1.next;
           l2=l2.next;   
         }  
           while(l2!=null)
           {
             cur.next=new ListNode((l2.val+flag)%10);
             flag=(l2.val+flag)/10;
             cur=cur.next;
             l2=l2.next;
           }          

        if(l2==null&&flag!=0)//考虑最后一位有进位的情况,l2 = [9,9,9,9,9,9,9], l1 = [9,9,9,9]输出:[8,9,9,9,0,0,0,1]
         {
            cur.next=new ListNode(flag);
         }     
     }
return head;
    }
}

结果展示

在这里插入图片描述

简化代码

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
       int flag=0;//进位标识符
        int l1_length=0;
        int l2_length=0;
        ListNode temp1=l1;
        ListNode temp2=l2;
        while(temp1!=null)//求链表1的长度
        {
            l1_length=l1_length+1;
            temp1=temp1.next;
        }
        while(temp2!=null)//求链表2的长度
        {
            l2_length=l2_length+1;
            temp2=temp2.next;
        }
     //先定义新链表的头结点
    ListNode head= new  ListNode ((l1.val+l2.val)%10);//取余数作为节点的值
    ListNode cur=head;//保留head,用cur代替head,后续操作cur
    flag=(l1.val+l2.val)/10;//求出进位
    l1=l1.next;
    l2=l2.next;
   
     if(l1_length==l2_length)
     {
         while(l1!=null)
         {
             cur.next= new  ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
             flag=(l1.val+l2.val+flag)/10;//取出进位
             cur=cur.next;  //这一句我是真怕形成环,但是还好过了                                     
             l1=l1.next;
             l2=l2.next;           
         }  
        if(l1==null&&flag!=0)//考虑最后一位有进位的情况,比如[2,4,3],[5,6,8].输出[7,0,2,1]
         {
            cur.next=new ListNode(flag);
         }     
     }
     if(l1_length>l2_length)
     {
       LengthNotEqual( l2,  l1,cur,flag);   //注意l1和l2的顺序,在LengthNotEqual函数中,是先判断比较短的链表是否遍历完毕,所以要把比较短的链表头放在第一个参数
     }

     if(l1_length<l2_length)
     {
         LengthNotEqual( l1,  l2,cur,flag);     
     }
     return head;
    }

 void LengthNotEqual(ListNode l1, ListNode l2,ListNode cur,int flag)
{
      while(l1!=null)
         {
           cur.next=new  ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
           flag=(l1.val+l2.val+flag)/10;//取出进位
           cur=cur.next; 
           l1=l1.next;
           l2=l2.next;   
         }  
           while(l2!=null)
           {
             cur.next=new ListNode((l2.val+flag)%10);
             flag=(l2.val+flag)/10;
             cur=cur.next;
             l2=l2.next;
           }          

        if(l2==null&&flag!=0)//考虑最后一位有进位的情况
         {
            cur.next=new ListNode(flag);
         }     
}
}

在这里插入图片描述

再简化代码

其实,两个链表长度相等是可以和另外两种情况合在一起计算的

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
       int flag=0;//进位标识符
        int l1_length=0;
        int l2_length=0;
        ListNode temp1=l1;
        ListNode temp2=l2;
        while(temp1!=null)//求链表1的长度
        {
            l1_length=l1_length+1;
            temp1=temp1.next;
        }
        while(temp2!=null)//求链表2的长度
        {
            l2_length=l2_length+1;
            temp2=temp2.next;
        }
     //先定义新链表的头结点
    ListNode head= new  ListNode ((l1.val+l2.val)%10);//取余数作为节点的值
    ListNode cur=head;//保留head,用cur代替head,后续操作cur
    flag=(l1.val+l2.val)/10;//求出进位
    l1=l1.next;
    l2=l2.next;
     
     if(l1_length>=l2_length)
     {
       LengthNotEqual( l2,  l1,cur,flag);   //注意l1和l2的顺序,在LengthNotEqual函数中,是先判断比较短的链表是否遍历完毕,所以要把比较短的链表头放在第一个参数
     }

     if(l1_length<l2_length)
     {
         LengthNotEqual( l1,  l2,cur,flag);     
     }
     return head;
    }

 void LengthNotEqual(ListNode l1, ListNode l2,ListNode cur,int flag)
{
      while(l1!=null)
         {
           cur.next=new  ListNode ((l1.val+l2.val+flag)%10);//取余数作为节点的值
           flag=(l1.val+l2.val+flag)/10;//取出进位
           cur=cur.next; 
           l1=l1.next;
           l2=l2.next;   
         }  
           while(l2!=null)
           {
             cur.next=new ListNode((l2.val+flag)%10);
             flag=(l2.val+flag)/10;
             cur=cur.next;
             l2=l2.next;
           }          

        if(l2==null&&flag!=0)//考虑最后一位有进位的情况
         {
            cur.next=new ListNode(flag);
         }     
}
}

在这里插入图片描述

总结

新创建链表时,定义链表头head之后,利用 cur=head,相当于复制了一份head,之后操作cur,不改变head,但是可以给链表追加节点

取余数 %10
取进位 /10

重复的代码可以封装为函数

构造函数直接创建新节点,不用为新节点指定名字,比如

 cur.next=new ListNode(flag);

在这里插入图片描述

参考题解

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        return this.addTwoNumbers2(l1, l2, 0);
    }

    public ListNode addTwoNumbers2(ListNode l1, ListNode l2, int a) {
        if (l1 == null && l2 == null) {
            return a == 0 ? null : new ListNode(a);
        }
        if (l1 != null) {
            a += l1.val;
            l1 = l1.next;
        }
        if (l2 != null) {
            a += l2.val;
            l2 = l2.next;
        }
        return new ListNode(a % 10, addTwoNumbers2(l1, l2, a / 10));
    }
}

在这里插入图片描述

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        return this.addTwoNumbers2(l1, l2, 0);
    }

    public ListNode addTwoNumbers2(ListNode l1, ListNode l2, int a) {
        if (l1 == null && l2 == null) {
            return a == 0 ? null : new ListNode(a);
        }
        if (l1 != null) {
            a += l1.val;
            l1 = l1.next;
        }
        if (l2 != null) {
            a += l2.val;
            l2 = l2.next;
        }
        ListNode node= new ListNode(a % 10);
        node.next=addTwoNumbers2(l1, l2, a / 10);
        return node;
    }
}

迭代版本

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        int carry=0;
        ListNode head=new ListNode(0);
        ListNode temp=head;
        while(l1!=null||l2!=null||carry!=0){
            int a=l1==null?0:l1.val;
            int b=l2==null?0:l2.val;
            carry=carry+a+b;
            int val=carry%10;
            carry/=10;
            l1=l1==null?null:l1.next;
            l2=l2==null?null:l2.next;          
            temp.next=new ListNode(val);
            temp=temp.next;
        }
        return head.next;
    }  
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值