Leetcode:链表(中等)——两数相加

原题链接:2. 两数相加 - 力扣(LeetCode)

目录

思路

注意点

易错点

完整代码


思路

本题的整体思路其实算是比较简单的:遍历两个链表然后进行相加,并将相加后的结果放到返回值的每个对应的节点中即可。

我认为这个题目还算是一个简化了的版本,因为题目提供的是单向链表,其中数字的放置顺序是实际数字的逆序了,也就是如果是数字 123 ,题目提供给我们的链表中 val 的顺序是:3、2、1,如果题目没有这样简化,估计还需要从后往前遍历链表进行相加,又是一个难点。

注意点

1. 数字相加之后如果满 10,需要往下一个节点进 1;并且还需要注意,此处的数字相加,不只是题目提供的两个链表中对应的值相加,还需要加上返回值中的上一节点是否有进 1。

假设:题目中提供的两个链表对应的节点值分别是 4 和 5,此时它们相加为 9 ,此时恰逢返回值中的上一节点是满 10 进 1,但是你没有加上这个进了的 1 ,那么结果就为 9 ,但实际是为 10 。

2. 两个链表长度可能不一,所以会出现不同时遍历完的情况。因此我们需要对遍历后的节点判空多加注意。

3. 需要注意一种特殊情况:假设两个链表中的最后一个值分别为:9、1,它们相加之后的结果为进 1 ,当前位为 0,但是还需要创建一个最后一位来表示进位了的 1 。但是此时两个链表都遍历完了,因此我们需要加上对这种特殊情况的判断。

易错点

1. 这个易错点,我不知道是不是我自己在做这个题时才会一直犯错的地方,就是新创建下一个节点的时机,我一开始是这样做的:

class Solution {
    public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode cur = new ListNode();
        ListNode head = cur;

        while(l1 != null && l2 != null) {
            //满10进1
            if (l1.val + l2.val + cur.val >= 10) {
                cur.next = new ListNode(1);
            } else {
                cur.next = new ListNode(0);
            }
            cur.val = (cur.val + l1.val + l2.val) % 10;

            l1 = l1.next;
            l2 = l2.next;
            cur = cur.next;
        }

        while(l1 != null) {
            if(l1.next != null) {
                if (l1.val + cur.val >= 10) {
                    cur.next = new ListNode(1);
                } else {
                    cur.next = new ListNode(0);
                }
                cur.val = (cur.val + l1.val) % 10;

                cur = cur.next;
                l1 = l1.next;
            }
        }
        while(l2 != null) {
            if(l2.next != null) {
                if (l2.val + cur.val >= 10) {
                    cur.next = new ListNode(1);
                } else {
                    cur.next = new ListNode(0);
                }

                cur.val = (cur.val + l2.val) % 10;

                cur = cur.next;
                l2 = l2.next;
            }
        }

        return head;
    }
}

其中 cur 表示返回值中,当前的节点。

我的想法是:在第一个循环中,如果相加之后满 10,就将下一节点创建后并赋初始值为 1,否则赋值为 0 。

但是这样的做法会有一个问题:就是最后一次进入循环时,会多创建一个节点,导致输出返回值时会多输出一个 0 ,这是一个额外创建的节点,本不应该存在。

参考了答案的做法后,修改为了:将 cur = cur.next 这步放在创建节点后进行,也就是创建当前节点而不是创建下一个节点(说起来有点绕,可能看代码比较好理解点)。

2. 如果将未遍历完的链表再额外加多一个 while 遍历完,可能会出现超出时间限制的情况,就像我上面的做法一样,所以尽量需要使用一个 while 循环将两个链表遍历完。

完整代码

class Solution {
    public static ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode cur = null;
        ListNode head = null;

        int flag = 0;

        while(l1 != null || l2 != null) {
            int n1 = l1 != null ? l1.val : 0;
            int n2 = l2 != null ? l2.val : 0;

            int tmp = flag + n1 + n2;

            if(tmp >= 10) {
                flag = 1;
            }else {
                flag = 0;
            }

            if(cur == null) {
                cur = new ListNode(tmp%10);
                head = cur;
            }else {
                cur.next = new ListNode(tmp%10);
                cur = cur.next;
            }

            if(l1 != null) {
                l1 = l1.next;
            }
            if(l2 != null) {
                l2 = l2.next;
            }
        }

        if(flag == 1) {
            cur.next = new ListNode(flag);
        }
        return head;
    }
}

上述代码中:

flag代表是否进 1 ;

while 循环中需要对 cur 是不是为第一个节点进行判断:如果为空即为第一个节点,此时就不能为创建 cur.next 节点,而是创建第一个节点,否则就为一般情况:先创建 cur.next 节点,再将其赋值给 cur,即为创建当前节点。由于要判断是否是第一个节点,因此 while 外创建 cur 时,须先将其置空,一开始我的做法是如下:

ListNode cur = new ListNode();
ListNode head = cur;

但是发现这样做,判断是否是第一个节点处就难以判断了,所以此做法不可取。

n1 和 n2 分别表示两个链表中对应的节点的值:如果当前节点为空,则赋为 0 ,此时就不会对相加的结果造成影响,这样就可以达到在一个 while 循环中遍历完两个不同长度的链表的目的;

tmp 表示相加后的结果;

最后一个 if 判断是为了解决上面所提到的特殊情况。

总体来说,这道题不能算难,但是细节可能比较多,需要注意的地方比较多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值