力扣LeetCode超详细题解:2. 两数相加(Java)

2. 两数相加

难度 中等

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

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

你可以假设除了数字 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]

提示:

  • 每个链表中的节点数在范围 [1, 100] 内
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

解题思路:根据题意我们可以知道输入的两个链表都是倒序存储的,即链表的头结点就是输入数字的个位数的值,这样我们就可以直接从头结点开始计算。对于结果链表有两种方式可以得到:一种是创建一个新的链表存储计算结果,每次计算都要新建一个节点,但是不会对原链表进行修改;另一种方法是在输入的任意一个链表中进行原地更新操作,将计算后要存储的结果更新到该节点。因为是进行加法运算,我们需要定义一个参数存储进位。在循环计算中要把输入的两个链表遍历完并且进位也是0时才能停止。

题中链表的定义:

class ListNode {
     int val;
     ListNode next;
     ListNode() {}
     ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

使用输入的链表原地更新结果:

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //进位的数值,l1中遍历到的值,l2中遍历到的值,要更新的结果
        int sign = 0, l1_val, l2_val, value;
        //使用l1作为结果链表,root用来记录头结点位置最后用于返回值
        ListNode root = l1;

        //l1和l2都遍历完,且进位为0时结束循环
        while (l1 != null || l2 != null || sign != 0){
            
            //计算完成之前l1不会指向null,原因在循环体倒数第二行
            l1_val = l1.val;
            //参照示例3,l2如果遍历完就赋值为0进行加法运算
            l2_val = l2 == null ? 0 : l2.val;

            value = l1_val + l2_val + sign;
            if(value >= 10){ //如果结果大于10,就要有进位
                /*
                因为是加法运算,进位只能是0或1,这里可以直接赋值
                如果是乘法的话下面的代码可以改成:
                sign = value / 10;
                vale = value % 10;
                */
                value -= 10;
                sign = 1;
            }
            else sign = 0;
            l1.val = value; //将结果更新到l1中

            // 如果l2还没遍历完,就进行下一位的计算。
            // 如果已经遍历完,此时l2应该是null,会在上面赋值为0进行运算,此处就不用操作
            if(l2 != null) l2 = l2.next;
            //如果l1要遍历完时l2还没有遍历完(比如l1=12,l2=1234)或者都遍历完了但是还有进位没处理,要在l1后面再加一个节点继续计算
            //这样也就保证了l1不会先遍历完,即l1不会先指向null
            if(l1.next == null && (l2 != null || sign != 0)) l1.next = new ListNode(0);
            l1 = l1.next;
        }
        return root;
    }
}

 

新建链表存储结果:

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        //进位的数值,l1中遍历到的值,l2中遍历到的值,要更新的结果
        int sign, l1_val, l2_val, value;
        
        //创建结果链表,确定头结点,初始化进位sign
        value = l1.val + l2.val;
        if(value >= 10){
            value -= 10;
            sign = 1;
        }
        else sign = 0;
        //root用来记录头结点位置最后用于返回值,l3用于插入结果子节点
        
        ListNode root = new ListNode(value);
        ListNode l3 = root;
        
        //上面已经计算了一次,所以这里要跳过一次
        l1 = l1.next;
        l2 = l2.next;
        //l1和l2都遍历完,且进位为0时结束循环
        while (l1 != null || l2 != null || sign != 0){
            //进入循环就代表肯定有计算未完成,要新建节点进行计算
            l3.next = new ListNode();
            l3 = l3.next;
            
            //如果有链表先被遍历完就赋值为0进行加法运算
            l1_val = l1 == null ? 0 : l1.val;
            l2_val = l2 == null ? 0 : l2.val;

            value = l1_val + l2_val + sign;
            if(value >= 10){ //如果结果大于10,就要有进位
                /*
                因为是加法运算,进位只能是0或1,这里可以直接赋值
                如果是乘法的话下面的代码可以改成:
                sign = value / 10;
                vale = value % 10;
                */
                value -= 10;
                sign = 1;
            }
            else sign = 0;
            l3.val = value; //将结果更新到结果链表中

            // 如果l1或l2还没遍历完,就进行下一位的计算。
            // 如果已经遍历完,此时l1或l2应该是null,会在上面赋值为0进行运算,此处就不用操作
            if(l1 != null) l1 = l1.next;
            if(l2 != null) l2 = l2.next;
        }
        return root;
    }
}

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值