题目
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
示例 1:
输入: num1 = "2", num2 = "3"
输出: "6"
示例 2:
输入: num1 = "123", num2 = "456"
输出: "56088"
说明:
- num1 和 num2 的长度小于110。
- num1 和 num2 只包含数字 0-9。
- num1 和 num2 均不以零开头,除非是数字 0 本身。
- 不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。
解题思路
本题不允许将输入的字符串转换为数值进行相乘,那么我们就将字符串转换成为字符串数组,利用竖式乘法进行计算。
例如:123 * 456
,可以转化为6 * 3+ 50 * 3 + 400 * 3 + 6 * 20 + 50 * 20 + 400 * 20 + 6 * 100 + 50 * 100 + 400 * 100
故需要两层循环,将两个数依次从左到右相乘。
索引 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|
res | 0 | 0 | 0 | 0 | 0 | 0 |
6 * 3 | 0 | 0 | 0 | 0 | 1 | 8 |
res | 0 | 0 | 0 | 0 | 1 | 8 |
50 * 3 | 0 | 0 | 0 | 1 | 5 | 0 |
res | 0 | 0 | 0 | 1 | 6 | 8 |
… | … | … | … | … | … | … |
设置一个数组res
来存储每次的计算结果
- 初始化数组长度为两个字符串长度和,该长度一定大于乘积长度。
- 从后往前取一个字符串,与另一个字符串相乘。
- 将乘积依次存储到数组中
3 * 6 = 18
那么我们就将18%10
存入数组的第一位,Math.floor(18 / 10)
存入数组的第二位- 下次循环,进一位进行求和再做重复操作。
- 最终将数组进行反转去零即可。
/**
* @param {string} num1
* @param {string} num2
* @return {string}
*/
var multiply = function (num1, num2) {
const res = new Array(num1.length + num2.length).fill(0); //初始化数组,长度大于乘积长度
for (let i = 0, last1 = num1.length - 1; i <= last1; i++) {
const n1 = Number(num1[last1 - i]);// 依次取从后往前取第一个字符串
for (let j = 0, last2 = num2.length - 1; j <= last2; j++) { // 依次从后往前取第二个字符串
const n2 = Number(num2[last2 - j]);
const x = res[i + j] + n1 * n2; //累加对应位置数值
res[i + j] = x % 10; //只保留一位数
res[i + j + 1] += Math.floor(x / 10); //如果和大于10,则进位
}
}
return res.reverse().join("").replace(/\b(0+)/gi,"") || "0"; //翻转拼接,清理多余的 0
};