我的LeetCode代码仓:https://github.com/617076674/LeetCode
原题链接:https://leetcode-cn.com/problems/multiply-strings/description/
题目描述:
知识点:字符串
思路:模拟手工算法
本题的思路很简单,就是单纯地模拟手工算法得出结果,但想把这个程序写得优美还是有难度的,下面将罗列我自己写程序时的一个个不同的实现版本。
版本一:
逻辑如下:
(1)数组stringBuilders里存储的是字符串num2中的各位上的数和num1相乘的结果,比如对于123 * 456而言,其存储的就是738,615,492。
(2)给数组stringBuilders中的元素添0,使其成为738,6150,49200。
(3)反转stringBuilders中的元素,使其成为837,0516,00294。
(4)对stringBuilders中的元素进行相加操作,使其成为88065。
(5)反转(4)中的结果,得到最终答案56088。
注意,在程序开始时,需要对乘数为0的情况做特殊处理,否则会出现类似0000的答案。
时间复杂度是O(n1 * n2),其中n1为字符串num1的长度,n2为字符串num2的长度。实现过程中使用了一个长度为n2的StringBuilder类型的数组,而数组中每个元素的长度是n1或者n1 + 1,因此空间复杂度为O(n1 * n2)。
JAVA代码:
public class Solution {
public String multiply(String num1, String num2) {
int n1 = num1.length();
int n2 = num2.length();
if(n1 == 1 && Integer.parseInt(num1) == 0) {
return num1;
}
if(n2 == 1 && Integer.parseInt(num2) == 0) {
return num2;
}
StringBuilder result = new StringBuilder();
StringBuilder[] stringBuilders = new StringBuilder[n2];
for (int i = n2 - 1; i >= 0; i--) {
StringBuilder stringBuilder = new StringBuilder();
int flag = 0;
for (int j = n1 - 1; j >= 0; j--) {
Integer integer = Integer.parseInt(num1.substring(j, j + 1)) * Integer.parseInt(num2.substring(i, i + 1));
stringBuilder.append((integer + flag) % 10);
flag = (integer + flag) / 10;
}
if(flag > 0) {
stringBuilder.append(flag);
}
stringBuilders[n2 - i - 1] = stringBuilder.reverse();
}
for (int i = 0; i < n2; i++) {
for (int j = 0; j < i; j++) {
stringBuilders[i].append(0);
}
}
for (int i = 0; i < n2; i++) {
stringBuilders[i] = stringBuilders[i].reverse();
}
int flag = 0;
int maxLen = 0;
for (int i = 0; i < n2; i++) {
maxLen = Math.max(maxLen, stringBuilders[i].length());
}
for (int i = 0; i < maxLen; i++) {
int sum = 0;
for (int j = 0; j < n2; j++) {
if(i < stringBuilders[j].length()) {
sum += Integer.parseInt(stringBuilders[j].substring(i, i + 1));
}
}
int num = (sum + flag) % 10;
flag = (sum + flag) / 10;
result.append(num);
}
if(flag > 0) {
result.append(flag);
}
return result.reverse().toString();
}
}
LeetCode解题报告:
版本二:
在版本一的逻辑中,我们前前后后对数组stringBuilders中的元素翻转了共3次,那么,肯定有可以简化的地方。版本二在版本一的基础上省去其中的2次翻转。
JAVA代码:
public class Solution {
public String multiply(String num1, String num2) {
int n1 = num1.length();
int n2 = num2.length();
if(n1 == 1 && Integer.parseInt(num1) == 0) {
return num1;
}
if(n2 == 1 && Integer.parseInt(num2) == 0) {
return num2;
}
StringBuilder result = new StringBuilder();
StringBuilder[] stringBuilders = new StringBuilder[n2];
for (int i = n2 - 1; i >= 0; i--) {
StringBuilder stringBuilder = new StringBuilder();
int flag = 0;
for (int j = n1 - 1; j >= 0; j--) {
Integer integer = Integer.parseInt(num1.substring(j, j + 1)) * Integer.parseInt(num2.substring(i, i + 1));
stringBuilder.append((integer + flag) % 10);
flag = (integer + flag) / 10;
}
if(flag > 0) {
stringBuilder.append(flag);
}
stringBuilders[n2 - i - 1] = stringBuilder;
}
for (int i = 0; i < n2; i++) {
for (int j = 0; j < i; j++) {
stringBuilders[i] = stringBuilders[i].insert(0, "0");
}
}
int flag = 0;
int maxLen = 0;
for (int i = 0; i < n2; i++) {
maxLen = Math.max(maxLen, stringBuilders[i].length());
}
for (int i = 0; i < maxLen; i++) {
int sum = 0;
for (int j = 0; j < n2; j++) {
if(i < stringBuilders[j].length()) {
sum += Integer.parseInt(stringBuilders[j].substring(i, i + 1));
}
}
int num = (sum + flag) % 10;
flag = (sum + flag) / 10;
result.append(num);
}
if(flag > 0) {
result.append(flag);
}
return result.reverse().toString();
}
}
LeetCode解题报告:
版本三:
去除版本二中给数组stringBuilders中的元素插入0的操作。
JAVA代码:
public class Solution {
public String multiply(String num1, String num2) {
int n1 = num1.length();
int n2 = num2.length();
if(n1 == 1 && Integer.parseInt(num1) == 0) {
return num1;
}
if(n2 == 1 && Integer.parseInt(num2) == 0) {
return num2;
}
StringBuilder result = new StringBuilder();
StringBuilder[] stringBuilders = new StringBuilder[n2];
for (int i = n2 - 1; i >= 0; i--) {
StringBuilder stringBuilder = new StringBuilder();
int flag = 0;
for (int j = n1 - 1; j >= 0; j--) {
Integer integer = Integer.parseInt(num1.substring(j, j + 1)) * Integer.parseInt(num2.substring(i, i + 1));
stringBuilder.append((integer + flag) % 10);
flag = (integer + flag) / 10;
}
if(flag > 0) {
stringBuilder.append(flag);
}
stringBuilders[n2 - i - 1] = stringBuilder;
}
int flag = 0;
for (int i = 0; i < stringBuilders[n2 - 1].length() + n2 - 1; i++) {
int sum = 0;
for (int j = 0; j < n2; j++) {
if(i - j < stringBuilders[j].length() && i - j >= 0) {
sum += Integer.parseInt(stringBuilders[j].substring(i - j, i - j + 1));
}
}
int num = (sum + flag) % 10;
flag = (sum + flag) / 10;
result.append(num);
}
if(flag > 0) {
result.append(flag);
}
return result.reverse().toString();
}
}
LeetCode解题报告:
版本四:
StringBuilder类的使用,能够方便我们写程序,但是会降低程序运行速度,因此我们舍弃之。
JAVA代码:
public class Solution {
public String multiply(String num1, String num2) {
int n1 = num1.length();
int n2 = num2.length();
char[] array1 = num1.toCharArray();
char[] array2 = num2.toCharArray();
if(array1[0] == '0' || array2[0] == '0') {
return "0";
}
String[] strings = new String[n2];
for (int i = n2 - 1; i >= 0; i--) {
String string = "";
int flag = 0;
for (int j = n1 - 1; j >= 0; j--) {
int num = (array1[j] - '0') * (array2[i] - '0');
string += (num + flag) % 10;
flag = (num + flag) / 10;
}
if(flag > 0) {
string += flag;
}
strings[n2 - i - 1] = string;
}
String result = "";
int flag = 0;
for (int i = 0; i < strings[n2 - 1].length() + n2 - 1; i++) {
int sum = 0;
for (int j = 0; j < n2; j++) {
if(i - j < strings[j].length() && i - j >= 0) {
sum += strings[j].charAt(i - j) - '0';
}
}
int num = (sum + flag) % 10;
flag = (sum + flag) / 10;
result = num + result;
}
if(flag > 0) {
result = flag + result;
}
return result;
}
}
LeetCode解题报告:
版本五:
对于字符串num2中的每一位数与字符串num1相乘所得的结果,不再分开计算最后相加,而是先全部累加,最后再考虑进位的影响。对于最终结果的第i + j位数,可以由num1数组的第i位数和num2数组的第j位数组成。
JAVA代码:
public class Solution {
public String multiply(String num1, String num2) {
int n1 = num1.length();
int n2 = num2.length();
if(n1 == 1 && Integer.parseInt(num1) == 0) {
return num1;
}
if(n2 == 1 && Integer.parseInt(num2) == 0) {
return num2;
}
int[] nums = new int[n1 + n2];
String result = "";
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
nums[i + j] += (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
}
}
int flag = 0;
for (int i = n1 + n2 - 2; i >= 0; i--) {
result = (nums[i] + flag) % 10 + result;
flag = (nums[i] + flag) / 10;
}
if(flag > 0) {
result = flag + result;
}
return result;
}
}
LeetCode解题报告: