两数相加问题

63 阅读2分钟

image.png

image.png

解题思路

  • 因为链表是从头到尾的线性数据结构,我们要保证输出是从后往前的顺序的话,就要定义一个初始链表list和一个用于计算的链表preNode
  • 链表的每一位都只能存一位数,所以我们需要定义一个值carry来存超过10的进位,永远只有0和1两个值
  • 定义循环的结束条件:因为链表最终会指向null,但是l1和l2的长度不一定一致,所以结束条件为l1 !== null || l2 !== null
  • 定义一个变量用来存储两数以及进位值相加的结果,result = l1.val + l2.val + carry
  • 循环的执行条件为:当l1的值被使用了之后,将l1.next赋值给l1,直到最后指向null,l2同理,都指向null时,满足循环结束条件
  • 为了保证最后的输出是链表:我们需要将定义一个新的链表,链表的值为result % 10,将preNode指向该结果,之后更新preNode为该新的链表,进行下一轮计算
  • 特殊情况的考虑:当结果链表的长度大于l1和l2中最长的长度时,说明他们相加在最后的时候进了一位,所以我们需要补充一个新的节点在链表最后
  • 最后,一定是返回list.next,不是list是因为list的初始值是0,是我们自己赋的值,真实结果在.next的节点中,不是返回preNode是因为,基于链表的线性特性,此时preNode已经指向了最后一个节点,我们要使用preNode的话,还要对齐进行链表的反转才行。

代码

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function(l1, l2) {

  let list = new ListNode(0);
  let carry = 0; // 进位
  let preNode = list;
  while (l1 !== null || l2 !== null) {
    let result = 0;
    if (l1) {
      result += l1.val;
      l1 = l1.next;
    }
    
    if (l2) {
      result += l2.val;
      l2 = l2.next;
    }
    
    result += carry;
    let newNode = new ListNode(result % 10);
    preNode.next = newNode;
    
    carry = result >= 10 ? 1: 0;
    preNode = newNode;
  }

  if (carry === 1) {
      preNode.next = new ListNode(1);
  }
  return list.next;
};