字符串相加-LeetCode415
约 687 字大约 2 分钟
2025-08-07
题目描述
给定两个非负整数 num1 和 num2,以字符串的形式表示,返回它们的和,结果也用字符串表示。
你不能使用任何内建的用于处理大整数的库(比如 BigInt),也不能直接将输入的字符串转换为整数。
解题思路
1. 补零对齐
由于两个字符串长度可能不同,我们需要先将较短的字符串在前面补零,使它们长度一致。这样可以方便从最低位(末尾)到最高位(开头)逐位相加。
用到的方法:padStart
padStart(targetLength, padString)
作用:返回一个新的字符串,原字符串左侧补上 padString,直到长度为 targetLength。- 示例:
let str = "77"; let padded = str.padStart(5, "0"); // "00077"
2. 从低位到高位逐位相加
- 从字符串末尾(最低位)开始,逐位相加。
- 每次相加时加上进位 carry。
- 结果大于等于 10 时,当前位存 res % 10,进位 carry 设为 1,否则 carry 设为 0。
- 最后如果还有进位,补到结果数组中。
3. 反转结果
- 因为是从低位往高位加的,结果数组需要反转后拼接成字符串。
代码实现
var addStrings = function(num1, num2) {
const len = Math.max(num1.length, num2.length);
const ans = [];
let carry = 0;
num1 = num1.padStart(len, '0');
num2 = num2.padStart(len, '0');
for (let i = len - 1; i >= 0; i--) {
const sum = parseInt(num1.charAt(i)) + parseInt(num2.charAt(i)) + carry;
ans.push(sum % 10);
carry = Math.floor(sum / 10);
}
if (carry) {
ans.push(carry);
}
return ans.reverse().join('');
};
更高效的解法
优化点
- 不需要补零,也不需要反转结果数组。
- 直接从两个字符串末尾向前遍历,逐位相加,结果直接插入字符串头部。
优化实现
var addStrings = function(num1, num2) {
let i = num1.length - 1, j = num2.length - 1, carry = 0;
let res = '';
while (i >= 0 || j >= 0 || carry) {
const n1 = i >= 0 ? num1.charCodeAt(i) - 48 : 0;
const n2 = j >= 0 ? num2.charCodeAt(j) - 48 : 0;
const sum = n1 + n2 + carry;
res = (sum % 10) + res;
carry = Math.floor(sum / 10);
i--;
j--;
}
return res;
};
取 num1 字符串第 i 个字符的 Unicode 编码,然后减去 48,把字符 '0'-'9' 转换为数字 0-9。
因为字符 '0' 的编码是 48,'1' 是 49,依次类推。所以:
- '0'.charCodeAt(0) - 48 = 0
- '5'.charCodeAt(0) - 48 = 5
- '9'.charCodeAt(0) - 48 = 9 这样可以高效地把数字字符转为对应的数字类型。
优势
- 时间复杂度:O(max(m, n)),m、n 分别为 num1 和 num2 的长度。
- 空间复杂度:O(1)(不计输出字符串),无需额外数组和补零操作,效率更高。
总结
- 本题考查字符串处理和模拟加法过程。
padStart
方法可以方便地补零对齐。- 优化解法可以省去补零和反转,效率更高,推荐使用。