【JS攻略Leetcode】No.2. Add Two Numbers(两数相加)

引言:用Js攻略leetcode中的算法,将会介绍自己的思路和注意点,一边学习一边愉快刷题呀。

问题1:

给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

思考:

  1. 342 + 465 = 807 也就是位位相加,注意一下每一位相加要加上进位,最后一次两个链表都到了结束,也要注意一下有没有进位:比如 99 + 1 = 100;
  2. 注意链表怎么把每个节点连接起来:每次生成一个listnode元素,通过当前listnode的下一个元素(cur_node.next)连城链。
  3. 最后返回一个列表,所以要给个头(result)指示列表起始的位置,再通过cur_node链接起链表串

代码:

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

var addTwoNumbers = function(l1, l2) {
    var val1 = 0;
    var val2 = 0;
    var carry = 0;//进位
    var result = null;//返回值
    var cur_node = null;

    var sumWithCarry = function(sum) {
        if(sum >= 10) {
            carry = 1;
            sum = sum - 10;
        } else {
            carry = 0;
        }
        return sum;
    }

    if(l1 || l2) {
        val1 = l1 ? l1.val : 0;
        val2 = l2 ? l2.val : 0;
        l1 = l1 ? l1.next : null;
        l2 = l2 ? l2.next : null;
        cur_node = new ListNode(sumWithCarry(val1 + val2));
        result = cur_node;
        while(l1 || l2) {
            val1 = l1 ? l1.val : 0;
            val2 = l2 ? l2.val : 0;
            l1 = l1 ? l1.next : null;
            l2 = l2 ? l2.next : null;
            cur_node.next = new ListNode(sumWithCarry(val1 + val2 + carry));
            cur_node = cur_node.next;
        }
        if(carry != 0) {
            cur_node.next = new ListNode(sumWithCarry(carry));
        }
    }
    return result;
};

问题2:

如果链表中的数字不是按逆序存储的呢?例如:
(3 -> 4 -> 2) + (4 -> 6 -> 5) = 8 -> 0 -> 7
符合人类观察的习惯: 342+465 = 807

思路:

  1. 思路1也是位位相加, 将两个列表中的值存入数组中:result_array = [3+4, 4+6, 2+5] = [7,10, 7], 再考虑进位为题变成 [ 8, 0, 7 ], 最后生成listnode连接起来。但是这种方法在列表不等长的情况下是不可行了,可跳过去看最后。
var addTwoNumbers = function(l1, l2) {
    var result_array = [];
    var result = null;//返回值
    var cur_node = null;
    var val1 = 0;
    var val2 = 0;
    while(l1 || l2) {
        val1 = l1 ? l1.val : 0;
        val2 = l2 ? l2.val : 0;
        l1 = l1 ? l1.next : null;
        l2 = l2 ? l2.next : null;
        result_array.push(val1 + val2)
    }
    for (var i = result_array.length - 1; i >= 0; i--) {
        if(result_array[i] >= 10) {
            result_array[i] = result_array[i] - 10;
            if(i > 0) {
                result_array[i -1] = result_array[i-1] + 1;
            } else {
                result_array.unshift(1);
                return;
            }
        }
    }
    if( result_array.length ){
        result = new ListNode(result_array[0]);
        cur_node = result;
        if(result_array.length > 1) {
            for (var i = 1; i <= result_array.length - 1; i ++) {
                cur_node.next = new ListNode(result_array[i]);
                cur_node = cur_node.next;
            }
        }
    }
    
    return result;
};

乍看起来非常完美,但是遇到了一个极其重要的逻辑问题:在处理两列表等长时这个方法可行,但是不等长时相加错误,比如: [9,9] + [2] = [9, 11]=[1,0,1], 但上述办法算出来是[11,9]=[1,1,9],所以在两列表不等长时,必须将相加位位置对齐,在另一个列表元素数组前面加上很多0;但是我觉得这种方式时间复杂度太高了。

  1. 思路2:然后我想为什么不能将它们变为数字再进行相加呢?[9,9] + [2] = 99 + 2 = 101 = [1,0,1]

代码:

var addTwoNumbers = function(l1, l2) {
    var result_array = [];
    var result_sum = 0;
    var result1 = 0;
    var result2 = 0;
    var result = null;//返回值
    var cur_node = null;
    
    var val1 = 0;
    var val2 = 0;

    while(l1 || l2) {
        val1 = l1 ? l1.val : 0;
        l1 = l1 ? l1.next : null;
        result1 = val1 + result1*10;
        val2 = l2 ? l2.val : 0;
        l2 = l2 ? l2.next : null;
        result2 = val2 + result2*10;
    }
    result_sum = result1 + result2;
    while(result_sum >= 10) {
        result_array.push(result_sum % 10);
        result_sum = ~~(result_sum / 10);
    }
    result_array.push(result_sum);

    if( result_array.length ){
        for (var i = result_array.length - 1; i >= 0; i--) {
            if(i == result_array.length - 1) {
                result = new ListNode(result_array[i]);
                cur_node = result;
            } else {
                cur_node.next = new ListNode(result_array[i]);
                cur_node = cur_node.next;
            }
        }
    }
    return result;
};

推荐阅读更多精彩内容

  • 题目描述: 给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回...
    coderzc阅读 80评论 0 0
  • 1.原题 You are given two non-empty linked lists representin...
    陌儿的百科全书阅读 68评论 0 2
  • 上通信的课就跟室友一起刷题玩,结果读题目读了半天,好歹我也是过了四级的人啊,怎么能这样,干脆百度题目意思…… 题目...
    做梦枯岛醒阅读 94评论 0 0
  • Description You are given two non-empty linked lists repr...
    CNSumi阅读 141评论 0 0
  • 在20多岁的年华里,还有大把青春的时候,我的心已经老了,再也不相信我能够等到爱情和爱我的人。 可惜了大把...
    尔西阅读 98评论 0 0
  • 问,“如何踏上朝向爱的旅程?”一旦你问了这个问题,旅程就已经开始了;你已人在路上了。这一点需要认出来——你已经在路...
    雅涵悠筱阅读 122评论 0 2
  • 沈寒的昨天:他都是在那群女生的奇异的目光下度过的……不管是抓到没抓到娃娃,她们的视线一直关注着他…怪渗人的……真...
    邢兄阅读 83评论 0 0
  • 自高考之后,再无触碰古文,亦未曾有落笔之兴。今,见一善思敏察之前辈,以古文忆往昔之年,言之成理,真真切切,颇有感触...
    洛洛C阅读 100评论 0 1
  • 雷艳妮0214 2016.3.19 原文:曾子曰:"慎终追远,民德归厚矣。” 译文:曾子说:“丧礼能慎重,祭祀...
    艳妮阅读 354评论 0 0