一、题目
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
注意: 不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
示例 1:
输入: num1 = "2", num2 = "3"
输出: "6"
示例 2:
输入: num1 = "123", num2 = "456"
输出: "56088"
提示:
1 <= num1.length, num2.length <= 200num1和num2只能由数字组成。num1和num2都不包含任何前导零,除了数字0本身。
二、解答
题目分析
本题的核心要求是实现两个以字符串形式呈现的非负整数的乘法运算,并且最终的乘积结果也要以字符串形式返回。同时,存在重要的限制条件,即不能运用任何内置的大整数库,也不能直接把输入的字符串转换为整数进行计算。
解题思路
由于不能直接将字符串转换为整数,我们需要模拟手工乘法的过程。具体步骤如下:
- 初始化结果数组:创建一个长度为
num1.length + num2.length的数组,用于存储每一位相乘的结果。 - 逐位相乘:从
num1和num2的最低位开始,逐位相乘,并将结果累加到结果数组的相应位置。 - 处理进位:遍历结果数组,处理每一位的进位。
- 去除前导零:去除结果数组前面的零。
- 转换为字符串:将结果数组转换为字符串。
示例分析
示例 1
- 输入:
num1 = "2",num2 = "3" - 分析:在手工乘法中,我们直接将
2和3相乘,得到6。所以最终输出为"6"。
示例 2
-
输入:
num1 = "123",num2 = "456" -
分析:
-
首先,将
123拆分为100 + 20 + 3,将456拆分为400 + 50 + 6。 -
然后,进行乘法运算:
3 * 6 = 183 * 50 = 1503 * 400 = 120020 * 6 = 12020 * 50 = 100020 * 400 = 8000100 * 6 = 600100 * 50 = 5000100 * 400 = 40000
-
最后,将所有结果相加:
18 + 150 + 1200 + 120 + 1000 + 8000 + 600 + 5000 + 40000 = 56088。所以最终输出为"56088"。
-
代码
class Solution {
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) {
return "0";
}
String ans = "0";
int m = num1.length(), n = num2.length();
for (int i = n - 1; i >= 0; i--) {
StringBuffer curr = new StringBuffer();
int add = 0;
for (int j = n - 1; j > i; j--) {
curr.append(0);
}
int y = num2.charAt(i) - '0';
for (int j = m - 1; j >= 0; j--) {
int x = num1.charAt(j) - '0';
int product = x * y + add;
curr.append(product % 10);
add = product / 10;
}
if (add != 0) {
curr.append(add % 10);
}
ans = addStrings(ans, curr.reverse().toString());
}
return ans;
}
public String addStrings(String num1, String num2) {
int i = num1.length() - 1, j = num2.length() - 1, add = 0;
StringBuffer ans = new StringBuffer();
while (i >= 0 || j >= 0 || add != 0) {
int x = i >= 0 ? num1.charAt(i) - '0' : 0;
int y = j >= 0 ? num2.charAt(j) - '0' : 0;
int result = x + y + add;
ans.append(result % 10);
add = result / 10;
i--;
j--;
}
ans.reverse();
return ans.toString();
}
}
代码分析
代码功能概述
这段代码定义了一个 Solution 类,其中包含两个方法:multiply 和 addStrings。multiply 方法的作用是实现两个以字符串形式表示的非负整数的乘法运算,并且将结果也以字符串形式返回。addStrings 方法则用于实现两个以字符串形式表示的非负整数的加法运算,同样将结果以字符串形式返回。
方法详细分析
multiply 方法
java
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) {
return "0";
}
String ans = "0";
int m = num1.length(), n = num2.length();
for (int i = n - 1; i >= 0; i--) {
StringBuffer curr = new StringBuffer();
int add = 0;
for (int j = n - 1; j > i; j--) {
curr.append(0);
}
int y = num2.charAt(i) - '0';
for (int j = m - 1; j >= 0; j--) {
int x = num1.charAt(j) - '0';
int product = x * y + add;
curr.append(product % 10);
add = product / 10;
}
if (add != 0) {
curr.append(add % 10);
}
ans = addStrings(ans, curr.reverse().toString());
}
return ans;
}
-
输入检查:
- 若
num1或者num2为"0",则直接返回"0",因为任何数与 0 相乘结果都为 0。
- 若
-
初始化结果:
- 把最终结果
ans初始化为"0"。
- 把最终结果
-
逐位相乘:
-
从
num2的最低位开始遍历,对于num2的每一位:- 创建一个
StringBuffer类型的curr用于存储当前位与num1相乘的结果。 - 为了模拟乘法运算中每一位相乘结果的右移,在
curr中添加相应数量的 0。 - 把
num2当前位的字符转换为整数y。 - 从
num1的最低位开始遍历,将num1当前位的字符转换为整数x,计算x和y的乘积并加上进位add,将结果的个位数添加到curr中,更新进位add。 - 若最后还有进位,将进位添加到
curr中。
- 创建一个
-
-
结果累加:
- 反转
curr并将其转换为字符串,调用addStrings方法将其与之前的结果ans相加,更新ans。
- 反转
-
返回结果:
- 最终返回
ans。
- 最终返回
addStrings 方法
java
public String addStrings(String num1, String num2) {
int i = num1.length() - 1, j = num2.length() - 1, add = 0;
StringBuffer ans = new StringBuffer();
while (i >= 0 || j >= 0 || add != 0) {
int x = i >= 0 ? num1.charAt(i) - '0' : 0;
int y = j >= 0 ? num2.charAt(j) - '0' : 0;
int result = x + y + add;
ans.append(result % 10);
add = result / 10;
i--;
j--;
}
ans.reverse();
return ans.toString();
}
-
初始化变量:
i和j分别指向num1和num2的最后一位,add用于存储进位,ans是一个StringBuffer用于存储相加的结果。
-
逐位相加:
-
只要
num1或者num2还有未处理的位,或者进位不为 0,就继续循环:- 获取
num1和num2当前位的数字,若已经遍历完则为 0。 - 计算当前位的和以及进位,将和的个位数添加到
ans中。 - 更新
i和j,指向前一位。
- 获取
-
-
反转结果:
- 由于是从低位到高位依次添加结果,所以最后需要反转
ans。
- 由于是从低位到高位依次添加结果,所以最后需要反转
-
返回结果:
- 将
ans转换为字符串并返回。
- 将
三、总结
-
核心方法:
multiply方法:通过模拟乘法运算,将num2逐位与num1相乘,再累加结果得到最终乘积。若任一输入为"0",则直接返回"0"。addStrings方法:实现两个字符串形式整数的加法,从低位到高位逐位相加并处理进位。
-
实现思路:
multiply方法借助addStrings方法累加每一位的乘法结果,模拟手动乘法过程;addStrings方法则通过循环逐位相加并处理进位
复杂度分析
- 时间复杂度:
multiply方法的时间复杂度为 O(m×n),其中 m 和 n 分别是num1和num2的长度。addStrings方法的时间复杂度为 O(max(m,n))。 - 空间复杂度:主要的空间开销在于存储中间结果和最终结果,空间复杂度为 O(m+n)。