夯实算法-字符串相乘

141 阅读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本身。

解题思路

使用数组储存得到的各位置乘积。一开始完全使用字符串处理,可以过但是速度比较慢,使用数组处理速度是完全用字符串处理的1/8左右。

字符串相乘或者相加其实都是差不多的,无非就是模拟我们做竖式的运算。在做竖式a*b的时候,我们一般分为两个步骤,首先,将b中的每一位,分别和a做乘法运算,然后再将乘法的结果加起来。

1.先筛选出最短的字符串和最长的,最短的当做乘数,最长的当做被乘数 2.创建一个StringBuffer数组,StringBuffer[i]表示被乘数和乘数的第i位的乘积,注意点:随着乘数的位数越高,对应的乘积的位数也应该越高。例如123 * 20,第一位0 和123相乘,结果为000,第二位2和123相乘,结果应该为2460,我们要把位数带上。 3.最后再把这些结果都相加 4.程序中是把数倒着计算的,sb[i]的i越小,表示乘数的位数越大。

代码实现

public String multiply(String num1, String num2) {
    if (num1.equals("0") || num2.equals("0")) return "0";
    char[] s1 = num1.toCharArray();
    char[] s2 = num2.toCharArray();
    int M = s1.length, N = s2.length;
    int[] res = new int[M + N];
    // 从右往左计算对角线累加和,并计算进位
    for (int i = M - 1; i >= 0; i--) {
        for (int j = N - 1; j >= 0; j--) {
            int k = i + j + 1; // 第k条对角线
            int sum = (s1[i] - '0') * (s2[j] - '0') + res[k]; // a*b + 进位
            res[k] = sum % 10; // 当前存个位
            res[k - 1] += sum / 10; // 进位应该加到左边一位上
        }
    }
    StringBuilder sb = new StringBuilder();
    for (int i = res[0] != 0 ? 0 : 1; i < res.length; i++) sb.append(res[i]);
    return sb.toString();
}

运行结果

Snipaste_2023-05-11_21-28-56.png

复杂度分析

  • 空间复杂度:O(1)
  • 时间复杂度:O(n)

掘金(JUEJIN) 一起分享知识, Keep Learning!