我正在参加「掘金·启航计划」
题目地址
给定两个以字符串形式表示的非负整数 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 😁)。
乘法的计算方式也很简单,过程如下:
- 首先需要翻转字符串,因为输入的字符串是数字直接转的字符串,但是我们计算要从低位向高位计算
- 将一个数字的每一位分别和另一个数字相乘,注意,这里不是直接相乘,而是分别和另一个数字的每一位相乘,累计结果为一个字符串
product
- 将上一步得到的所有
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('')
}
拿下!😀