【题目描述】
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
示例 1:
输入: num1 = "2", num2 = "3"
输出: "6"
示例 2:
输入: num1 = "123", num2 = "456"
输出: "56088"
提示:
1)1 <= num1.length, num2.length <= 200
2)num1 和 num2 只能由数字组成。
3)num1 和 num2 都不包含任何前导零,除了数字0本身。
【解题代码】
package string;
public class Multiply {
public static void main(String[] args) {
String num1 = "2", num2 = "3";
String result = new Multiply().multiply(num1, num2);
System.out.println(result);
}
private String multiply(String num1, String num2) {
int i, j;
int sum;
int len = num1.length() + num2.length();
int[] map = new int[len];
for (i = num1.length() - 1; i >= 0; i--) {
for (j = num2.length() - 1; j >= 0; j--) {
sum = (num1.charAt(i) - 48) * (num2.charAt(j) - 48);
map[len - i - j - 2] += sum;
}
}
StringBuffer sb = new StringBuffer();
for (i = 0; i < len - 1; i++) {
map[i + 1] += map[i] / 10;
sb.append(map[i] % 10);
}
sb.append(map[i] % 10);
String result = sb.reverse().toString().replaceAll("^0+", "");
return result.equals("") ? "0" : result;
}
}
【解题思路】
拿到题目有种历史重回的感觉,记得上大学的时候有个同学参加学校竞赛时做过同样的题目,当时就觉得不太简单,具体解法也记不起了。根据题目描述和示例,反复思考,终于想出解决思路:将两个乘数字符串每个字符数字,两两(假设索引分别为i和j)相乘根据两个数的位置之和设置结果的位置,并数值处理大于10的情况
【解题步骤】
- 定义各个变量:包括字符串两两相乘循环变量i,j 乘积值。两个字符串长度和,乘积结果的每一位数值数组等
int i, j; int sum; int len = num1.length() + num2.length(); int[] map = new int[len];
- 依次将两个字符串的每个数两两相乘,并将结果设置到对应的数组位置
for (i = num1.length() - 1; i >= 0; i--) { for (j = num2.length() - 1; j >= 0; j--) { sum = (num1.charAt(i) - 48) * (num2.charAt(j) - 48); map[len - i - j - 2] += sum; } }
- 对数组里从0开始每一个大于十数的数,将个位数留下,十位数移到上一位
StringBuffer sb = new StringBuffer(); for (i = 0; i < len - 1; i++) { map[i + 1] += map[i] / 10; sb.append(map[i] % 10); } sb.append(map[i] % 10);
- 最后将map所有数字转换成字符串并进行反转,即可获得乘积最终结果
String result = sb.reverse().toString().replaceAll("^0+", ""); return result.equals("") ? "0" : result;
【思考总结】
- 这道题真的很有意思,也非常实用,拜托了数据变量位数的限制,解决了超超级长度的两数相乘的问题;
- 这道题解法的核心在于:两两(假设索引分别为i和j)相乘根据两个数的位置之和设置结果的位置;
- LeetCode解题之前,一定不要看题解,看了就“破功”了!