LeetCode热题(JS版) -43. 字符串相乘

110 阅读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中的数字类型可以表示非常大的数,因此我们可以使用数字类型来进行计算。
  • 从乘数的最低位开始,一位一位地与被乘数相乘。将乘积存储在一个数组中,数组的下标表示乘积对应的位数,例如,数组的第0个元素表示个位上的乘积,第1个元素表示十位上的乘积,以此类推。
  • 将每一位的乘积相加得到最终结果。这里需要注意的是,位数相同的乘积可能会产生进位,因此需要将进位保存下来,加到高位上。
  • 将结果数组转换成字符串形式返回。

JavaScript代码实现:

var multiply = function(num1, num2) {
    if (num1 === '0' || num2 === '0') return '0'; // 特判:如果有一个字符串为0,直接返回0

    const n1 = num1.length, n2 = num2.length;
    const pos = new Array(n1 + n2).fill(0); // 初始化结果数组,长度为num1.length + num2.length

    for (let i = n1 - 1; i >= 0; i--) { // 从乘数的最低位开始遍历
        const x = +num1[i]; // 将乘数的当前位转换成数字
        for (let j = n2 - 1; j >= 0; j--) { // 从被乘数的最低位开始遍历
            const y = +num2[j]; // 将被乘数的当前位转换成数字
            const product = x * y; // 计算当前位的乘积
            
            const p1 = i + j, p2 = i + j + 1; // 计算当前位的结果应该存储在结果数组的哪个位置
            const sum = product + pos[p2]; // 计算当前位的结果加上进位的值

            pos[p1] += Math.floor(sum / 10); // 更新进位
            pos[p2] = sum % 10; // 更新当前位的结果
        }
    }

    let res = '';
    for (const p of pos) { // 将结果数组转换成字符串形式
        if (p !== 0 || res !== '') res += p; // 跳过高位的0
    }
    return res;
};

image.png

  • 时间复杂度:O(mn)O(mn),其中 mmnn 分别是两个字符串的长度。
  • 空间复杂度:O(m+n)O(m + n),需要存储中间结果和最终结果。