sl1673495 / leetcode-javascript

:beers: 喝杯小酒,一起做题。前端攻城狮从零入门算法的宝藏题库,根据知名算法老师的经验总结了 100+ 道 LeetCode 力扣的经典题型 JavaScript 题解和思路。已按题目类型分 label,一起加油。

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

两数相加-3

sl1673495 opened this issue · comments

commented

给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

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

示例:

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

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

思路

这题的题目描述写的很烂,其实就是两个链表 2 -> 4 -> 35 -> 6 -> 4 相加而已,原因里非要把数字倒过来不知道整什么。

需要注意的点:

  1. 4 + 6 这种得出的结果 >= 10,需要在下一次求和中进位,也就是把下一次求和的结果 +1。
  2. 有可能链表的长度不同,注意处理比较长那个链表的尾部,并且单个链表的时候也要注意之前求出的和有没有大于 10 待进位。
  3. 有可能所有链表都处理完了,最后还有进位没处理(最后一位的求和正好结果为 10),那么就需要在尾部再新追加一个链表节点,并且值为 1

在代码中我们直接把链表求和的双链表单链表情况都封装在了一个方法里,通过一个初始是否传入 listNode2 来建立一个标志位便于后续判断,并且双链表求和完了以后会递归的调用自身,变成处理单链表的状态。

最后返回的是 root.next,这是因为我们在 while 循环中直接第一步就是 cur.next = new ListNode(),如果不这么做的话我们还需要在 traverse 的方法中判断是否是头部节点来决定是要对 next 节点还是 cur 节点赋求和的值,非常麻烦。这个技巧叫做傀儡节点,非常实用。

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
let addTwoNumbers = function (l1, l2) {
  let i = 0
  let root = new ListNode()
  let cur = root
  let plus = false

  let traverse = (node1, node2) => {
    let isDouble = !!node2
    while (isDouble ? node1 && node2 : node1) {
      cur.next = new ListNode()
      cur = cur.next

      let sum = node1.val + (plus ? 1 : 0)
      if (isDouble) {
        sum += node2.val
      }

      if (sum >= 10) {
        sum %= 10
        plus = true
      } else {
        plus = false
      }
      cur.val = sum

      node1 = node1.next
      if (isDouble) {
        node2 = node2.next
      }
    }

    if (node1) {
      traverse(node1)
    }
    if (node2) {
      traverse(node2)
    }
  }

  traverse(l1, l2)

  if (plus) {
    cur.next = new ListNode(1)
  }

  return root.next
}

这题编号应该是2

commented

var addTwoNumbers = function(l1, l2) {
let p3=l3=new ListNode()
let p1=l1
let p2=l2
let car=0
while(p1||p2){
let v1=p1?p1.val:0
let v2=p2?p2.val:0
let v3=v1+v2+car
car=Math.floor(v3/10)
p3.next=new ListNode(v3%10)
if(p1)p1=p1.next
if(p2)p2=p2.next
p3=p3.next
}
if(car){
p3.next=new ListNode(car)
}
return l3.next
};

因为是倒序,所以两个链表从第一位就要开始相加记录进位,理解了这个就很好做:

var addTwoNumbers = function (l1, l2) {
    const resHead = new ListNode('head');
    let temp = resHead;
    let progression = 0;
    while (l1 || l2) {
        const val1 = l1 ? l1.val : 0;
        const val2 = l2 ? l2.val : 0;
        const sum = val1 + val2 + progression;
        progression = Math.floor(sum / 10);
        temp.next = new ListNode(sum % 10);
        temp = temp.next;

        if (l1) l1 = l1.next;
        if (l2) l2 = l2.next;
    }

    if (progression > 0) temp.next = new ListNode(progression);
    return resHead.next;
}