目录
- 字符串相乘
- 题目
- 示例 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 分别表示 和 的长度,并且它们均不为 0,则 和 的乘积的长度为 。简单证明如下:
- ;
由于 和 的乘积的最大长度为 ,因此创建长度为 的数组 $\textit{ansArr} $用于存储乘积。对于任意,的结果位于 ,如果 ,则将进位部分加到 。
最后,将数组 转成字符串,如果最高位是 0 则舍弃最高位。
还可以用另外一种方法改写。我们把两个数相乘看成是两个多项式相乘,因为任何一个数都可以表示成为
的形式,也就相当于对多项式
在 x = 10 处求值。当两个数 相乘的时候,我们也可以认为这两个数是两个多项式
相乘的结果 C(x) = A(x) \times B(x) 在 x = 10 处求值。我们可以这样表示 C(x):
这里
于是我们就可以顺序求解 ,每次 地选取下标和为 i 的一组 。求到
- 顺序求解 的过程相当于集中计算
- 而方法二相当于每对 对 算贡献(注意这里的 并不是题目中的 ,$a_i $下标越小,代表的位权越小,而 下标越小,代表的位权越大)
它们的本质是一样的,并且时间复杂度都是 。我们再仔细的观察 c_i 的形式:
它揭示了多项式乘法的另一面:c_i 序列其实是 a_i 序列和 b_i 序列的卷积,即:
完整代码
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();
}
}