43. 字符串相乘
题目
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
示例 1:
输入: num1 = "2", num2 = "3"
输出: "6"
示例 2:
输入: num1 = "123", num2 = "456"
输出: "56088"
说明:
num1 和 num2 的长度小于110。
num1 和 num2 只包含数字 0-9。
num1 和 num2 均不以零开头,除非是数字 0 本身。
不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。
解法
- a*b = b个a相加
思路很简单,有了ListNode相加的基础,代码整体不难。但需要从char变成数字,再变为char,略麻烦,且!尽管num1和num2的长度小于110,貌似仅需做110次运算,但实际上!运算次数超过110^2,直接爆炸。
- 细分乘法
来自leetcode评论区:
index: 0 1 2 3 4
1 2 3
* 4 5
---------
1 5
1 0
0 5
---------
0 6 1 5
1 2
0 8
0 4
---------
0 5 5 3 5
故可以推测出:
- 对于num1的第i位*num2的第j位,其对应的是相乘后结果的第[i+j]和[i+j+1]位。
- 对于对于两个长度分别为len1和len2的数相乘后的结果位数最大为[len1+len2];
代码如下:
class Solution {
public String multiply(String num1, String num2) {
if(num1.equals("0") || num2.equals("0")){
return "0";
}else{
int [] sum = new int [num1.length()+num2.length()];
for(int i=0; i<num1.length(); i++){
for(int j=0; j<num2.length(); j++){
int add = Character.getNumericValue(num1.charAt(i)) * Character.getNumericValue(num2.charAt(j));
int ge = add % 10;
int shi = add / 10;
int temp1 = sum[i+j+1] + ge;
int temp2 = sum[i+j] + shi;
sum[i+j+1] = temp1 % 10;
sum[i+j] = (temp2 + temp1 / 10) % 10;
int C = (temp2 + temp1 / 10) / 10;
int fir = i+j;
while(C>0 && fir>0){
temp1 = sum[fir-1] + C;
sum[fir-1] = temp1 % 10;
C = temp1 / 10;
fir--;
}
}
}
StringBuilder builder = new StringBuilder();
for(int i=0;i<num1.length()+num2.length();i++){
builder.append(String.valueOf(sum[i]));
}
return builder.toString().replaceFirst("^(0+)", "");
}
}
}
显然有点麻烦。原因在于上述代码是手推代码的倒推顺序,不得不考虑向前进位x个。
如果按照手推代码的顺序,就只需考虑[i+j-1]的进位(如果存在的话),
如下:
class Solution {
public String multiply(String num1, String num2) {
if(num1.equals("0") || num2.equals("0")){
return "0";
}else{
int [] sum = new int [num1.length()+num2.length()];
for(int i=num1.length()-1; i>=0; i--){
for(int j=num2.length()-1; j>=0; j--){
int add = Character.getNumericValue(num1.charAt(i)) * Character.getNumericValue(num2.charAt(j));
int temp1 = sum[i+j+1] + add % 10;
int temp2 = sum[i+j] + add / 10;
sum[i+j+1] = temp1 % 10;
sum[i+j] = (temp1 / 10 + temp2) % 10;
int C = (temp1 / 10 + temp2) / 10;
if(C>0){
sum[i+j-1] += C;
}
}
}
StringBuilder builder = new StringBuilder();
for(int i=0;i<num1.length()+num2.length();i++){
builder.append(String.valueOf(sum[i]));
}
return builder.toString().replaceFirst("^(0+)", "");
}
}
}
可以看到,for循环并不是很丝滑,原因是没有考虑到乘法第k步和第k+1步错位的关系,
for(int i = num1.length()-1; i >= 0; i--) {
for(int j = num2.length()-1; j >= 0; j--) {
int bitmul = (num1.charAt(i)-'0') * (num2.charAt(j)-'0');
bitmul += mul[i+j+1]; // 先加低位判断是否有新的进位
mul[i+j] += bitmul / 10;
mul[i+j+1] = bitmul % 10;
}
}
完美

浙公网安备 33010602011771号