一、题目描述
1.题目内容
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
原题链接:https://leetcode.cn/problems/multiply-strings
2.样例
二、解决方案
1.算法流程
1)分析(竖式计算)
这道题本质上其实是经典的“大数相乘”问题,两个非负整数num1、num2比较大时,若进行乘法运算会导致“溢出”,所以要转换思想,将给定的整数转为字符串模拟手动竖式乘法运算。这里直接计算两个字符串的乘积结果,也就是省略了“大数相乘”中将整数转为字符串的步骤。
上小学的时候,我们都学过竖式乘法的计算过程,这里举个简单的例子,以此归纳出我们的算法流程:
num1=123,num2=456
从num2的个位开始,依次与num1的每一位进行乘法计算,满十进一,最后将每一位所得的值对应相加得到最终的运算结果。
下图中,红色填充表示num2每一位与num1对应的计算结果,蓝色字体表示进位(简单的竖式计算,相信大家都会),可看到因为最高位也有可能大于10,需要进位,所以最终结果的长度len(result)<=len(num1)+len(num2):
清晰了竖式计算的过程以后,实现“字符串相乘”就变得简单多了。
2)算法流程
- 当num1或num2中有一个为“0”时结果直接为0,终止计算;
- 创建一个整数数组result用于存储计算结果(数组元素默认初始化为0),其长度为lenOfNum1+lenOfNum2;
- 从个位开始, 以num1为基础,逐次与num2的所有位进行乘积运算,得到对应位的计算值currentOfNum1*currentOfNum2,若currentOfNum1*currentOfNum2>=10,则需要进位;
- 在计算的过程中,每得到一个值,就相应地记录在result的对应位置,以累加的方式进行元素的更新;
需要注意,计算过程中num1、num2为字符串形式,乘积结果使用整型数组来存储,在去除前导零后,将计算结果转换为字符串输出。
看代码吧,代码更清晰…
2.Java实现
1)核心代码
public String multiply(String num1, String num2) {
// 当num1或num2中有一个为“0”时结果直接为0,终止计算
if ((num1.length()==1&&num1.charAt(0)=='0')||(num2.length()==1&&num2.charAt(0)=='0')){
return "0";
}
int lenOfNum1=num1.length();
int lenOfNum2=num2.length();
// 计算结果的最大长度为两个整数各自长度的和
int[] result=new int[lenOfNum1+lenOfNum2]; // 创建一个整数数组用于存储计算结果
for(int i=0;i<lenOfNum1;i++){
int k=result.length-1-i; // 从个位开始,依次计算
int currentOfNum1=num1.charAt(lenOfNum1-1-i)-'0'; // num1此时对应位的字符
for(int j=0;j<lenOfNum2;j++){
int currentOfNum2=num2.charAt(lenOfNum2-1-j)-'0'; // num2此时对应位的字符
result[k]+=currentOfNum1*currentOfNum2; // 更新数组元素
if(result[k]>=10){ // 判断此处是否需要进位
result[k-1]+=(result[k]/10);
result[k]%=10;
}
k--; // 计算更高位的值
}
}
// 去除前导0(最高位无进位时,则存在前导零的情况)
int i=0;
while (result[i]==0){
i++;
}
// 拼接乘法运算结果(此时i指向计算结果中的第一个非0数字)
StringBuilder resStr=new StringBuilder();
while (i<result.length){
resStr.append(result[i]);
i++;
}
return resStr.toString();
}
2)完整测试代码
import java.util.Arrays;
/**
* LeetCode43:字符串相乘(模拟手算乘法)
* */
public class MultiplyStrings {
public static void main(String[] args) {
MultiplySolution solution=new MultiplySolution();
String num1 = "123";
String num2 = "456";
System.out.println(solution.multiply(num1,num2));
}
}
class MultiplySolution {
public String multiply(String num1, String num2) {
if ((num1.length()==1&&num1.charAt(0)=='0')||(num2.length()==1&&num2.charAt(0)=='0')){
return "0";
}
int lenOfNum1=num1.length();
int lenOfNum2=num2.length();
int[] result=new int[lenOfNum1+lenOfNum2]; // 创建一个整数数组用于存储计算结果
for(int i=0;i<lenOfNum1;i++){
int k=result.length-1-i;
int currentOfNum1=num1.charAt(lenOfNum1-1-i)-'0';
for(int j=0;j<lenOfNum2;j++){
int currentOfNum2=num2.charAt(lenOfNum2-1-j)-'0';
result[k]+=currentOfNum1*currentOfNum2;
if(result[k]>=10){
result[k-1]+=(result[k]/10);
result[k]%=10;
}
k--;
}
}
// 处理计算结果的前导零
int i=0;
while (result[i]==0){
i++;
}
// 拼接乘法运算结果(此时i指向计算结果中的第一个非0数字)
StringBuilder resStr=new StringBuilder();
while (i<result.length){
resStr.append(result[i]);
i++;
}
// System.out.println(Arrays.toString(result));
return resStr.toString();
}
}