[415]字符串相加
思路
- 模拟竖式计算,先从个位开始相加,相加超过 10 就进 1;
- 如果当前位相加不超过 10,那就简单,直接相加,然后将这个位的数替换;
- 要先从个位开始相加,就需要遍历,所以先找出两数中短的那个数,减少遍历次数;
- 需要注意,进位时,可能会产生连续进位的情况,这种情形下,本文采用递归去进位;
- 对较短的数进行遍历时,获取当前两数的长度差,然后加上遍历的 i 值,即是此次位置上进行相加时,较长数中对应的位置;
实现
获取更短的那个数:
const minNum = num1.length >= num2.length ? num2 : num1;
获取更长的那个数,同时这个数会作为初始值进入迭代、递归计算:
let res = num1.length >= num2.length ? num1 : num2;
开始遍历较短的数,PS:两个数相差的长度 gap,由于进位后可能会变化,所以需要在遍历时,实时获取:
for (let i = minNum.length - 1; i >= 0; i--) {
// 两个数相差的长度,由于进位后可能会变化,所以需要在遍历时,实时获取
const gap = Math.abs(res.length - minNum.length);
res = helper(res, gap + i, Number(minNum[i]));
}
每次遍历,获取当前位相加 后的 res,最终返回的 res 就是结果。
helper 就是实现当前位相加的函数。
要实现当前位相加,需要注意:
- 如果加到了最高位,即当前位的下标
startIdx为 0 时,不论是否进位,只需要剔除当前和currMax的最高位,然后拼接当前位的两数相加的和sum,不论是否进位都是这样; - 如果没有到最高位,那就直接对当前位
sum取模,然后替换掉当前和sum的对应位startIdx,接下来再判断是否需要进位; - 如果
sum > 9则需要进位,递归调用helper函数
function addStrings(num1: string, num2: string): string {
// 更短的那个数
const minNum = num1.length >= num2.length ? num2 : num1;
// 更长的那个数
let res = num1.length >= num2.length ? num1 : num2;
// 遍历较小数时,对齐大数的位时,采用gap+i
for (let i = minNum.length - 1; i >= 0; i--) {
// 两个数相差的长度,由于进位后可能会变化,所以需要在遍历时,实时获取
const gap = Math.abs(res.length - minNum.length);
res = helper(res, gap + i, Number(minNum[i]));
}
return res;
/**
*
* @param currMax 当前的较长的数字的【字符串形式】
* @param startIdx 在进行计算时,较大数的起始位置
* @param currNum 遍历较小数,从最末尾(个位)开始遍历
*/
function helper(currMax: string, startIdx: number, currNum: number) {
// 当前位相加
const sum = Number(currMax[startIdx]) + currNum;
if (startIdx === 0) {
// 已经加到大数的最高位了,不需要考虑进位,直接拼接最高位的字符串
currMax = String(sum) + currMax.slice(1);
} else {
// 非最高位,此时要考虑进位的情况
// 先默认不进位,直接加(取模)
currMax = currMax.slice(0, startIdx) + String(sum % 10) + currMax.slice(startIdx + 1);
if (sum > 9) {
// 需要进位,所以往前走一位,拿1去加
return helper(currMax, startIdx - 1, 1);
}
}
return currMax;
}
}
\