LeetCode日记——[415]字符串相加

258 阅读2分钟

[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;
  }
}

\