[Leetcode][javascript]第2题: 两数相加

题目

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。

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

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

解法

官方解析地址:https://leetcode-cn.com/articles/add-two-numbers/

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */

var addTwoNumbers = function(l1, l2) {
    let dummyHead = new ListNode(0),carry = 0,curr = dummyHead;
     
    while (l1 !== null || l2 !== null) {
        let num1 = l1 ? l1.val : 0;
        let num2 = l2 ? l2.val : 0;
        let sum = num1 + num2 + carry;
        curr.next = new ListNode(sum % 10);
        curr = curr.next;
        carry = sum > 9 ? 1 : 0;
        l1 = l1 ? l1.next : l1;
        l2 = l2 ? l2.next : l2;
    }

    if (carry > 0) {
        curr.next = new ListNode(1);
    }

    return dummyHead.next;
};

个人踩坑总结

  1. 把链表当数组
    一开始,我看懂了链表的意思,但不太明白 JavaScript 里是怎么个情况,而且给的测试用例里的输入是两个数组,我就简单粗暴的当数组写了。但提交的时候怎么都通过不了。
    然后我观察到注释里有个 ListNode 构造函数,就想办法输出了下addTwoNumbers 里那两个参数的val、next、和 length 属性。发现结果很奇特,虽然看着像是个数组,其实并不是。如:输入[2,4,3],那它的 val 是 2 ,next 显示为 [4,3],length 为 undefined。这时我大概理解了链表的意思。

  2. 没想到先new ListNode(),再返回其next,写了个中间函数
    我想到了用一个中间参数不停的在循环后存next,就像 curr.next = new ListNode(sum % 10); curr = curr.next; 但是当时没想明白,总是无法满足所有的测试用例,就先放弃了这种方法,准备换一种思路先实现效果。后来搜了下资料,发现了 https://segmentfault.com/a/1190000008706650 ,参考里面的 append 方法我自己又写了个中间方法,但只满足这道题的话,明显不需要每次都重新循环出最后一个 next 再赋值。最后实现的代码看着挺笨,而且比较费时。推荐另一篇类似的博客《javascript中的链表结构》,讲的比较详细 https://www.cnblogs.com/tylerdonet/p/5880088.html 。

    /**
     * Definition for singly-linked list.
     * function ListNode(val) {
     *     this.val = val;
     *     this.next = null;
     * }
     */
    /**
     * @param {ListNode} l1
     * @param {ListNode} l2
     * @return {ListNode}
     */
    var addTwoNumbers = function(l1, l2) {
        let l3;
        let pre = 0;
        function _append(_val){
            let _l3 = new ListNode(_val);
            let l4;
            if(l3){
                l4 = l3;
                while(l4.next){
                    l4 = l4.next;
                }
                l4.next = _l3;
            }else{
                l3 = _l3;
            };
        }
        
        while(l1.val || l2.val || l1.val === 0 || l2.val === 0){
            let sum = (l1.val||0 ) + (l2.val||0) + pre;
            pre = sum>9 ? 1 : 0;
            _append(sum%10);
            l1 = l1.next || {};
            l2 = l2.next || {};
            
        }
    
        if(pre){
            _append(1);
        }
    
        return l3;
    };
    
  3. 根据官方解析,实现不 先new ListNode(),再返回其 next
    现在看到官方解析后的代码,忽然知道怎么改成我之前想要的效果了。但代码整体看来每次循环都要多判断一次。

    /**
     * Definition for singly-linked list.
     * function ListNode(val) {
     *     this.val = val;
     *     this.next = null;
     * }
     */
    /**
     * @param {ListNode} l1
     * @param {ListNode} l2
     * @return {ListNode}
     */
    
    var addTwoNumbers = function(l1, l2) {
        let dummyHead,carry = 0,curr;
         
        while (l1 !== null || l2 !== null) {
            let num1 = l1 ? l1.val : 0;
            let num2 = l2 ? l2.val : 0;
            let sum = num1 + num2 + carry;
            if(!dummyHead){
                dummyHead = new ListNode(sum % 10);
                curr = dummyHead;
            }else{
                curr.next = new ListNode(sum % 10);
                curr = curr.next;
            }
            carry = sum > 9 ? 1 : 0;
            l1 = l1 ? l1.next : l1;
            l2 = l2 ? l2.next : l2;
        }
    
        if (carry > 0) {
            curr.next = new ListNode(1);
        }
    
        return dummyHead;
    };
    

你可能感兴趣的:(leetcode)