「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战」。
题目描述
给定两个以字符串形式表示的非负整数 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的数相乘,最终结果不会超过m+n。因此最终数组申请长度就为m+n。然后就是两个数的第i位和第j位相乘的结果,会存放在最终结果的第i+j位和第i+j+1位中。
- 在优化的代码运行中,mul[i+j]可能会出现大于10的数,但是因为遍历是从低位到高位相乘的,在填充mul数组时首先保证了低位是个位数,至于高位,在后序遍历中会作为低位保证其为个位数。所以代码可以执行。因为首先保证结果不会大于m+n,所以数组够用。第一位不会大于等于10.
具体过程如下:
- 长度是n和长度是m的数字相乘,最多只有n + m位,为了方便计算,将num1和num2反向存储到A[]和B[]中,即位数低的在数组前面,且开一个大小是n + m的C[]存储计算后的答案。
- 两个数相乘时,将A[i] * B[j]的结果累加到C[i + j]中,最后C[i + j]表示i + j这个位数的值是Ci + j
- 由于C[]数组中的某些位数字可能是大于等于10的,我们从0枚举到n + m - 1,进行满10进位, 将所有位的值全部变成个位数。
- 最后将C[]数组反转输出。
注意:最终得到的数组C[]的高位可能包含前导0,因此在反转之前要先去除高位前导0
代码
class Solution {
public String multiply(String num1, String num2) {
int n = num1.length(), m = num2.length();
int[] A = new int[n], B = new int[m];
for (int i = n - 1; i >= 0; i--) A[n - 1 - i] = num1.charAt(i) - '0'; //反向存贮
for (int i = m - 1; i >= 0; i--) B[m - 1 - i] = num2.charAt(i) - '0';
int[] C = new int[n + m];
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
C[i + j] += A[i] * B[j];
int t = 0; //存贮进位
for (int i = 0; i < C.length; i++) {
t += C[i];
C[i] = t % 10;
t /= 10;
}
int k = C.length - 1;
while (k > 0 && C[k] == 0) k--; //去除前导0
StringBuilder sb = new StringBuilder();
while (k >= 0) sb.append((char)(C[k--] + '0')); //反转
return sb.toString();
}
}
运行结果
执行结果:通过
执行用时:2 ms
内存消耗:41.8 MB