04月10, 2020

[leetcode]2. 两数相加

2. 两数相加

这个题目需要使用 js 来实现单项列表,并把两个链表的每一项相加,返回一个新的链表。

题目地址

描述

image.png

解析

既然是要用列表来操作,那我们首先应该定义列表。
从题目的注释中我们可以看到已经给我们定义好结构了


 //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) {
  const currNode1 = l1
  const currNode2 = l2
  let num1 = 0; let num2 = 0
  let i = 0
  let currNode = currNode1
  while (currNode.next) {
    num1 += currNode.val * (Math.pow(10, i))
    currNode = currNode.next
    i++
  }
  num1 += currNode.val * (Math.pow(10, i))
  console.log({ num1 })
  i = 0
  currNode = currNode2
  while (currNode.next) {
    num2 += currNode.val * (Math.pow(10, i))
    currNode = currNode.next
    i++
  }
  num2 += currNode.val * (Math.pow(10, i))
  console.log({ num2 })

  let sum = 0
  let tmp = 0

  sum = num1 + num2
  console.log({ sum })

  currNode = new ListNode(0)

  tmp = sum % 10
  sum = parseInt(sum / 10)
  const resNode = new ListNode(tmp)
  currNode = resNode

  while (sum >= 1) {
    tmp = sum % 10
    sum = parseInt(sum / 10)
    const tmpNode = new ListNode(tmp)
    currNode.next = tmpNode
    currNode = tmpNode
  }

  return resNode
}


这个代码初看没有问题,而且在数组项较少时没有问题

addTwoNumbers([2, 6], [1, 2, 3])

输出:

[3, 8, 3]


可是当我们的数组项较多时,就不可行了。

const nodeList1 = createListNodeFromArray()
const nodeList2 = createListNodeFromArray([5, 6, 4])

const nodeList = addTwoNumbers([1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [5,6,4])


这个时候再转成整型,已经超出了最大范围。

所以这种方法不可行

二、 按位相加


很自然的,我们就想到了按位相加这种方法。
按位相加,需要考虑两个数之和大于10时,需要进一。

/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function (l1, l2) {
  let currNode1 = l1
  let currNode2 = l2
  let tmp = 0
  let intoOne = 0
  let val1 = 0
  let val2 = 0

  const retNode = new ListNode(0)
  let currNode = retNode
  let tmpNode = null
  while (true) {
    val1 = currNode1 ? currNode1.val : 0
    val2 = currNode2 ? currNode2.val : 0
    tmp = val1 + val2 + intoOne
    if (tmp >= 10) {
      // 进1
      tmp -= 10
      intoOne = 1
    } else {
      intoOne = 0
    }

    if (currNode == null) {
      currNode = new ListNode(tmp)
    } else {
      tmpNode = new ListNode(tmp)
      currNode.next = tmpNode
      currNode = tmpNode
    }

    currNode1 = currNode1 && currNode1.next
    currNode2 = currNode2 && currNode2.next
    if (currNode1 == null && currNode2 == null) {
      break
    }
  }

  return retNode.next
}


上面的代码也是有问题的。就是没有考虑最后一项相加时大于10的情况。

addTwoNumbers([5], [5])

输出:

错误:
[0]

正确:
[0, 1]


针对这种情况,需要在循环结束之后判断最后一项是否大于10

  if (intoOne === 1) {
    tmpNode = new ListNode(1)
    currNode.next = tmpNode
    currNode = tmpNode
  }


完整代码如下:

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

function ListNode (val) {
  this.val = val
  this.next = null
}

function createListNodeFromArray (arr) {
  const headerNode = new ListNode(arr[0])
  let currNode = headerNode

  for (let i = 1; i < arr.length; i++) {
    const element = arr[i]

    const tmpNode = new ListNode(element)
    currNode.next = tmpNode
    currNode = tmpNode
  }

  return headerNode
}

/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
var addTwoNumbers = function (l1, l2) {
  let currNode1 = l1
  let currNode2 = l2
  let tmp = 0
  let intoOne = 0
  let val1 = 0
  let val2 = 0

  const retNode = new ListNode(0)
  let currNode = retNode
  let tmpNode = null
  while (true) {
    val1 = currNode1 ? currNode1.val : 0
    val2 = currNode2 ? currNode2.val : 0
    tmp = val1 + val2 + intoOne
    if (tmp >= 10) {
      tmp -= 10
      intoOne = 1
    } else {
      intoOne = 0
    }

    if (currNode == null) {
      currNode = new ListNode(tmp)
    } else {
      tmpNode = new ListNode(tmp)
      currNode.next = tmpNode
      currNode = tmpNode
    }

    currNode1 = currNode1 && currNode1.next
    currNode2 = currNode2 && currNode2.next
    if (currNode1 == null && currNode2 == null) {
      break
    }
  }
  if (intoOne === 1) {
    tmpNode = new ListNode(1)
    currNode.next = tmpNode
    currNode = tmpNode
  }
  return retNode.next
}

const nodeList1 = createListNodeFromArray([2, 4, 3])
const nodeList2 = createListNodeFromArray([5, 6, 7])

const nodeList = addTwoNumbers(nodeList1, nodeList2)

let currNode = nodeList
while (currNode.next) {
  console.log(currNode.val)
  currNode = currNode.next
}
console.log(currNode.val)

本文链接:http://blog.guansixu.cn/post/[leetcode]2. liang-shu-xiang-jia.html

-- EOF --

Comments