[ CodeWar ] - 010:大数相加

459 阅读2分钟

系列文章

题目

img-02

需求:

  • 传入两个整数形式的字符串,需要返回它们的和的字符串

解析

这道题乍一看仿佛一道送分题,不假思索的把代码写下来去跑单测:

const sumStrings = (a, b) => (parseInt(a) + parseInt(b)).toString();

单测结果如下:

img-02

其实题目中已经写得很清楚了:

A string representation of an integer will contain no characters besides the ten numerals "0" to "9".

那么显然这里是一个大数相加的问题。

大数相加,说起来好像是一个很复杂的问题,实际上,只要小学上过数学课,应该是有一定思路的:

img-03

这里我们只要实现以上算法即可:

  • 首先通过 Math.max() 获取两个整数中大着的长度
  • 然后通过 padStart() 将小整数的位数补足
    • a - 1020301920120
    • b - 0000101023019
  • 通过循环计算两个整数每一位相加
    • 通过第一个变量记录两个数相加的结果
    • 通过第二个变量记录两数相加之后的进位

关键点如上,代码按部就班实现就好:

function sumStrings(a, b{
  const len = Math.max(a.length, b.length);
  a = a.padStart(len, 0);
  b = b.padStart(len, 0);
  let c = 0,
    s = 0,
    ret = "";
  for (let i = len - 1; i >= 0; i--) {
    s = parseInt(a[i]) + parseInt(b[i]) + c;
    c = Math.floor(s / 10);
    ret = (s % 10) + ret;
  }
  if (c === 1) {
    ret = "1" + ret;
  }
  return ret.replace(/\b(0+)/gi"");
}

优化

我们总结上述算法可以发现以下特点:

  • 进位只会是 0 或 1

那么这里我们就可以借助 Boolean 的特性:

function sumStrings(a, b{
  let arrA = a.split(""),
    arrB = b.split(""),
    carry = 0,
    sum = "";

  while (arrA.length || arrB.length || carry) {
    carry = carry + (~~arrA.pop() + ~~arrB.pop());
    sum = (carry % 10) + sum;
    carry = carry > 9;
  }

  return sum.replace(/^0+/"");
}

其实核心算法和上面还是一样的。