目录

  • 字符串相乘
  • 题目
  • 示例 1
  • 示例 2
  • 提示
  • 解答
  • 解题思路
  • 完整代码


字符串相乘

题目

给定两个以字符串形式表示的非负整数 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本身。

解答

解题思路

令 m 和 n 分别表示 Java 两个字符串集合 差集 java两个字符串相乘_字符串Java 两个字符串集合 差集 java两个字符串相乘_Java 两个字符串集合 差集_02 的长度,并且它们均不为 0,则 Java 两个字符串集合 差集 java两个字符串相乘_字符串Java 两个字符串集合 差集 java两个字符串相乘_Java 两个字符串集合 差集_02 的乘积的长度为 Java 两个字符串集合 差集 java两个字符串相乘_字符串_05。简单证明如下:

  • Java 两个字符串集合 差集 java两个字符串相乘_算法_06
  • Java 两个字符串集合 差集 java两个字符串相乘_java_07

由于 Java 两个字符串集合 差集 java两个字符串相乘_字符串Java 两个字符串集合 差集 java两个字符串相乘_Java 两个字符串集合 差集_02 的乘积的最大长度为 Java 两个字符串集合 差集 java两个字符串相乘_字符串_10,因此创建长度为 Java 两个字符串集合 差集 java两个字符串相乘_字符串_10 的数组 $\textit{ansArr} $用于存储乘积。对于任意Java 两个字符串集合 差集 java两个字符串相乘_算法_12Java 两个字符串集合 差集 java两个字符串相乘_数据结构_13的结果位于 Java 两个字符串集合 差集 java两个字符串相乘_算法_14,如果 Java 两个字符串集合 差集 java两个字符串相乘_Java 两个字符串集合 差集_15,则将进位部分加到 Java 两个字符串集合 差集 java两个字符串相乘_字符串_16
最后,将数组 Java 两个字符串集合 差集 java两个字符串相乘_字符串_17转成字符串,如果最高位是 0 则舍弃最高位。
还可以用另外一种方法改写。我们把两个数相乘看成是两个多项式相乘,因为任何一个数都可以表示成为
Java 两个字符串集合 差集 java两个字符串相乘_字符串_18
的形式,也就相当于对多项式Java 两个字符串集合 差集 java两个字符串相乘_字符串_19
在 x = 10 处求值。当两个数 Java 两个字符串集合 差集 java两个字符串相乘_java_20相乘的时候,我们也可以认为这两个数是两个多项式
Java 两个字符串集合 差集 java两个字符串相乘_数据结构_21
相乘的结果 C(x) = A(x) \times B(x) 在 x = 10 处求值。我们可以这样表示 C(x):Java 两个字符串集合 差集 java两个字符串相乘_java_22
这里Java 两个字符串集合 差集 java两个字符串相乘_Java 两个字符串集合 差集_23
于是我们就可以顺序求解 Java 两个字符串集合 差集 java两个字符串相乘_字符串_24,每次 Java 两个字符串集合 差集 java两个字符串相乘_字符串_25地选取下标和为 i 的一组 Java 两个字符串集合 差集 java两个字符串相乘_字符串_26。求到 Java 两个字符串集合 差集 java两个字符串相乘_字符串_24

  • 顺序求解 Java 两个字符串集合 差集 java两个字符串相乘_java_28的过程相当于集中计算 Java 两个字符串集合 差集 java两个字符串相乘_java_28
  • 而方法二相当于每对 Java 两个字符串集合 差集 java两个字符串相乘_算法_30Java 两个字符串集合 差集 java两个字符串相乘_算法_31算贡献(注意这里的 Java 两个字符串集合 差集 java两个字符串相乘_java_32并不是题目中的 Java 两个字符串集合 差集 java两个字符串相乘_java_33,$a_i $下标越小,代表的位权越小,而 Java 两个字符串集合 差集 java两个字符串相乘_java_33下标越小,代表的位权越大)

它们的本质是一样的,并且时间复杂度都是 Java 两个字符串集合 差集 java两个字符串相乘_java_35。我们再仔细的观察 c_i 的形式:
Java 两个字符串集合 差集 java两个字符串相乘_数据结构_36
它揭示了多项式乘法的另一面:c_i 序列其实是 a_i 序列和 b_i 序列的卷积,即:
Java 两个字符串集合 差集 java两个字符串相乘_Java 两个字符串集合 差集_37

完整代码

class Solution {
    public String multiply(String num1, String num2) {
        if (num1.equals("0") || num2.equals("0")) {
            return "0";
        }
        int m = num1.length(), n = num2.length();
        int[] ansArr = new int[m + n];
        for (int i = m - 1; i >= 0; i--) {
            int x = num1.charAt(i) - '0';
            for (int j = n - 1; j >= 0; j--) {
                int y = num2.charAt(j) - '0';
                ansArr[i + j + 1] += x * y;
            }
        }
        for (int i = m + n - 1; i > 0; i--) {
            ansArr[i - 1] += ansArr[i] / 10;
            ansArr[i] %= 10;
        }
        int index = ansArr[0] == 0 ? 1 : 0;
        StringBuffer ans = new StringBuffer();
        while (index < m + n) {
            ans.append(ansArr[index]);
            index++;
        }
        return ans.toString();
    }
}