内容介绍
给定两个以字符串形式表示的非负整数
num1
和num2
,返回num1
和num2
的乘积,它们的乘积也表示为字符串形式。注意:不能使用任何内置的 BigInteger 库或直接将输入转换为整数。
示例 1:
输入: num1 = "2", num2 = "3" 输出: "6"示例 2:
输入: num1 = "123", num2 = "456" 输出: "56088"提示:
1 <= num1.length, num2.length <= 200
num1
和num2
只能由数字组成。num1
和num2
都不包含任何前导零,除了数字0本身。
完整代码
char* addStrings(char* num1, char* num2) {
int i = strlen(num1) - 1, j = strlen(num2) - 1, add = 0;
char* ans = malloc(sizeof(char) * (i + j + 5));
int ansLen = 0;
while (i >= 0 || j >= 0 || add != 0) {
int x = i >= 0 ? num1[i] - '0' : 0;
int y = j >= 0 ? num2[j] - '0' : 0;
int result = x + y + add;
ans[ansLen++] = result % 10;
add = result / 10;
i--;
j--;
}
for (int i = 0; i < ansLen / 2; i++) {
char t = ans[i];
ans[i] = ans[ansLen - 1 - i];
ans[ansLen - 1 - i] = t;
}
for (int i = 0; i < ansLen; i++) {
ans[i] += '0';
}
ans[ansLen++] = 0;
return ans;
}
char* multiply(char* num1, char* num2) {
int m = strlen(num1), n = strlen(num2);
char* ans = malloc(sizeof(char) * 2);
ans[0] = '0', ans[1] = 0;
if ((m == 1 && num1[0] == '0') || (n == 1 && num2[0] == '0')) {
return ans;
}
for (int i = n - 1; i >= 0; i--) {
char* curr = malloc(sizeof(char) * (n + m + 5));
int currLen = 0;
int add = 0;
for (int j = n - 1; j > i; j--) {
curr[currLen++] = 0;
}
int y = num2[i] - '0';
for (int j = m - 1; j >= 0; j--) {
int x = num1[j] - '0';
int product = x * y + add;
curr[currLen++] = product % 10;
add = product / 10;
}
while (add != 0) {
curr[currLen++] = add % 10;
add /= 10;
}
for (int i = 0; i < currLen / 2; i++) {
char t = curr[i];
curr[i] = curr[currLen - 1 - i];
curr[currLen - 1 - i] = t;
}
for (int i = 0; i < currLen; i++) {
curr[i] += '0';
}
curr[currLen++] = 0;
char* tmp = addStrings(ans, curr);
free(ans), free(curr);
ans = tmp;
}
return ans;
}
思路详解
addStrings
函数思路详解
addStrings
函数用于实现两个大整数字符串的加法。其输入是两个表示整数的字符串 num1
和 num2
,输出是它们相加后的字符串结果。
步骤分析:
-
初始化变量:
i
和j
分别初始化为num1
和num2
字符串的最后一个字符的索引。add
用于存储进位,初始为 0。ans
是结果字符串的动态分配数组,长度为i + j + 5
以确保足够存储结果及结束符。
-
逐位相加:
- 使用
while
循环,条件是i
、j
至少有一个大于等于 0 或者有进位add
。 - 在每次循环中,将
num1[i]
和num2[j]
转换为对应的整数值x
和y
,如果已经超出字符串范围则设为 0。 - 将
x
、y
和add
相加,得到当前位的和result
,并将result % 10
存储到ans
中,同时更新add
为result / 10
。
- 使用
-
反转结果字符串:
- 因为计算时是从低位到高位进行的,所以需要将结果字符串反转过来。
- 通过一个循环交换
ans
的前后对应字符。
-
转换为字符表示:
- 将结果字符串中的每个数字字符加上
'0'
,以转换为正确的字符表示。
- 将结果字符串中的每个数字字符加上
-
添加字符串结束符:
- 在结果字符串的末尾添加字符串结束符
\0
。
- 在结果字符串的末尾添加字符串结束符
-
返回结果:
- 返回结果字符串
ans
。
- 返回结果字符串
multiply
函数思路详解
multiply
函数用于实现两个大整数字符串的乘法。其输入是两个表示整数的字符串 num1
和 num2
,输出是它们相乘后的字符串结果。
步骤分析:
-
初始化变量:
m
和n
分别存储num1
和num2
字符串的长度。ans
是结果字符串的动态分配数组,初始为'0'
,表示乘积为 0。
-
边界情况处理:
- 如果任一字符串长度为 1 且值为
'0'
,则直接返回结果ans
。
- 如果任一字符串长度为 1 且值为
-
逐位相乘:
- 使用外层循环,逆序遍历
num2
的每一位字符。 - 对于
num2
的每一位字符,初始化一个临时字符串curr
用于存储该位的乘积。 - 内层循环遍历
num1
的每一位字符,计算乘积并存储到curr
中。 - 每次乘积可能产生进位,需要处理这些进位。
- 使用外层循环,逆序遍历
-
处理进位和反转字符串:
- 将
curr
中的数字反转,并转换为字符表示。
- 将
-
累加乘积:
- 使用
addStrings
函数将当前位的乘积curr
累加到结果ans
上。 - 更新
ans
为新的累加结果。
- 使用
-
返回结果:
- 循环结束后,返回累加的最终结果字符串
ans
。
- 循环结束后,返回累加的最终结果字符串
以上两个函数都采用了模拟手工计算的方式,逐位处理每一位的加法或乘法,同时考虑进位问题,并通过字符串反转来得到正确的顺序。这种方法的优点是直观且容易理解,但需要注意内存管理和字符串操作的正确性。
知识点精炼
-
动态内存分配:
malloc
函数用于动态分配内存,返回指向分配内存块的指针。- 在使用动态分配的内存时,需要确保在不再使用时调用
free
函数释放内存,以避免内存泄漏。
-
字符串长度获取:
strlen
函数用于计算字符串的长度,返回值是字符串中的字符数量,不包括字符串结束符\0
。
-
字符串反转:
- 通过一个循环交换字符串的前后对应字符,实现字符串的反转。
-
字符串相加:
- 将两个字符串中的每一位数字相加,并考虑进位,将结果存储在动态分配的数组中。
-
字符串相乘:
- 采用模拟手工计算的方式,逐位相乘并累加,处理进位问题,实现字符串的乘法。
-
整数转换为字符串:
- 通过循环,将每个数字字符转换为对应的整数值,并加上字符
'0'
,以转换为正确的字符表示。
- 通过循环,将每个数字字符转换为对应的整数值,并加上字符
-
字符串结束符:
- 在字符串的末尾添加字符串结束符
\0
,表示字符串的结束。
- 在字符串的末尾添加字符串结束符
-
指针的使用:
- 动态分配的内存块通过指针来访问,需要确保指针指向的有效性。
-
循环结构:
- 使用
while
循环和for
循环实现字符串的逐位处理和乘法累加。
- 使用
-
边界条件处理:
- 在函数开始时检查输入字符串的长度和值,以处理边界情况,如其中一个字符串长度为 1 且值为
'0'
。
- 在函数开始时检查输入字符串的长度和值,以处理边界情况,如其中一个字符串长度为 1 且值为