大数加法
题目描述
以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。
数据范围:
- 字符串长度 (1 \leq \text{len}(s), \text{len}(t) \leq 100000)
- 字符串仅由
'0'
到'9'
构成
要求:
- 时间复杂度 (O(n))
示例
示例 1
输入:
s = "1"
, t = "99"
输出:
"100"
说明:
(1 + 99 = 100)
示例 2
输入:
s = "114514"
, t = ""
输出:
"114514"
解题思路
模拟手工加法
-
从低位到高位逐位相加:
- 从两个字符串的末尾开始,逐位相加,并处理进位。
- 如果某一位的和大于等于 10,则产生进位。
-
处理不等长字符串:
- 如果两个字符串长度不同,较短的字符串在高位补 0。
-
处理最终进位:
- 如果最高位相加后仍有进位,需要在结果的最前面添加一个
1
。
- 如果最高位相加后仍有进位,需要在结果的最前面添加一个
-
结果反转:
- 由于是从低位到高位计算的,最终结果需要反转。
代码实现
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 逆转字符串
void reverseString(char* str, int length) {
int start = 0;
int end = length - 1;
while (start < end) {
// 交换首尾字符
char temp = str[start];
str[start] = str[end];
str[end] = temp;
// 移动指针
start++;
end--;
}
}
// 计算两个大整数的和
char* solve(char* s, char* t) {
// 获取两个字符串的长度
int len1 = strlen(s);
int len2 = strlen(t);
// 如果其中一个字符串为空,直接返回另一个字符串
if (len1 == 0) {
char* result = (char*)malloc(sizeof(char) * (len2 + 1));
strcpy(result, t);
return result;
}
if (len2 == 0) {
char* result = (char*)malloc(sizeof(char) * (len1 + 1));
strcpy(result, s);
return result;
}
// 结果的最大长度(取较长的长度 + 1,用于进位)
int len = (len1 > len2 ? len1 : len2) + 1;
// 初始化进位标志
int jinwei = 0;
int a = 0, b = 0;
// 分配结果字符串的内存
char* result = (char*)malloc(sizeof(char) * (len + 1)); // +1 用于存储 '\0'
// 从字符串末尾开始逐位相加
for (int i = 0; i < len - 1; i++) {
// 获取 s 的当前位(如果还有剩余)
if (len1 > 0) {
a = s[--len1] - '0'; // 将字符转换为整数
} else {
a = 0;
}
// 获取 t 的当前位(如果还有剩余)
if (len2 > 0) {
b = t[--len2] - '0'; // 将字符转换为整数
} else {
b = 0;
}
// 计算当前位的和(包括进位)
int sum = a + b + jinwei;
// 如果和大于等于 10,设置进位标志
if (sum >= 10) {
jinwei = 1;
sum -= 10; // 减去 10,取个位数
} else {
jinwei = 0; // 清除进位标志
}
// 将结果存储为字符
result[i] = sum + '0'; // 将整数转换为字符
}
// 如果最后还有进位,在结果末尾添加 '1'
if (jinwei) {
result[len - 1] = '1';
result[len] = '\0'; // 添加字符串结束符
reverseString(result, len); // 逆转结果字符串
} else {
result[len - 1] = '\0'; // 添加字符串结束符
reverseString(result, len - 1); // 逆转结果字符串
}
return result;
}
代码解析
1. reverseString
函数
- 用于反转字符串。
- 通过交换首尾字符实现。
2. solve
函数
- 初始化:
- 获取两个字符串的长度。
- 分配结果字符串的内存。
- 逐位相加:
- 从字符串末尾开始,逐位相加,并处理进位。
- 如果某一位的和大于等于 10,则产生进位。
- 处理最终进位:
- 如果最高位相加后仍有进位,在结果的最前面添加一个
1
。
- 如果最高位相加后仍有进位,在结果的最前面添加一个
- 结果反转:
- 由于是从低位到高位计算的,最终结果需要反转。
- 返回结果:
- 返回计算结果的字符串。
复杂度分析
- 时间复杂度:(O(n)),其中 (n) 是两个字符串中较长的长度。
- 空间复杂度:(O(n)),用于存储结果字符串。
测试用例
测试用例 1
输入:
s = "1"
, t = "99"
输出:
"100"
测试用例 2
输入:
s = "114514"
, t = ""
输出:
"114514"
测试用例 3
输入:
s = "123"
, t = "456"
输出:
"579"
测试用例 4
输入:
s = "999"
, t = "1"
输出:
"1000"
总结
通过模拟手工加法的方式,我们可以高效地计算两个大整数的和。以下是代码的核心逻辑:
步骤 | 说明 |
---|---|
逐位相加 | 从低位到高位逐位相加 |
处理进位 | 如果和大于等于 10,产生进位 |
结果反转 | 将结果反转以得到正确顺序 |
处理空字符串 | 直接返回非空字符串的副本 |