leetcode-43-字符串相乘

574 阅读1分钟

我正在参加「掘金·启航计划」
题目地址

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

示例 1:

输入: num1 = "2", num2 = "3" 输出: "6" 示例 2:

输入: num1 = "123", num2 = "456" 输出: "56088"

提示:

1 <= num1.length, num2.length <= 200 num1 和 num2 只能由数字组成。 num1 和 num2 都不包含任何前导零,除了数字0本身。

解题思路

这个题解题思路比较简单,难点在于一点编码技巧。
首先 JavaScript 遵循 IEEE754 标准,javascript 里数字 Number 类型,也就是 64-bit 的浮点数存在 安全整数 问题(对于这块不了解的朋友可以自行了解下,这里不做展开),超过安全整数范围的数字精度就会丢失,本题就是让我们处理早期这种超范围数字的计算问题(现在有了 BigInt 😁)。
乘法的计算方式也很简单,过程如下:

  1. 首先需要翻转字符串,因为输入的字符串是数字直接转的字符串,但是我们计算要从低位向高位计算
  2. 将一个数字的每一位分别和另一个数字相乘,注意,这里不是直接相乘,而是分别和另一个数字的每一位相乘,累计结果为一个字符串 product
  3. 将上一步得到的所有 product 相加,就得到了两数相乘的结果

如果直接按上述步骤编写代码,肯定是可以解题的,但是因为存在大量对字符串的操作,所以效率相对低一些,这里我们可以用一个足够长的数组,存储计算结果,那多长是足够长呢,我们通过简单的计算就可以得出。
99 * 999 = 98901 999 * 9999 = 9989001
可以看到,两个数相乘,乘积最大长度也就是两个数的长度之和。

代码实现

var multiply = function (num1, num2) {
  if (num1 === '0' || num2 === '0') {
    return '0'
  }

  num1 = num1.split('').reverse().join('')
  num2 = num2.split('').reverse().join('')
  const m = num1.length
  const n = num2.length
  const result = new Array(m + n).fill(0)

  for (let i = 0; i < m; i++) {
    let carry = 0

    for (let j = 0; j < n; j++) {
      const product = num1[i] * num2[j] + carry
      result[i + j] += product % 10
      carry = Math.floor(product / 10)

      if (result[i + j] > 9) {
        result[i + j] -= 10
        carry++
      }
    }

    if (carry) {
      result[i + n] += carry

      if (result[i + n] > 9) {
        result[i + n] -= 10
        result[i + n + 1]++
      }
    }
  }

  result.reverse()
  
  while (result[0] === 0) {
    result.shift()
  }

  return result.join('')
}

拿下!😀