目录

题目描述

415. 字符串相加

image-20230304213815480

题意分析

给定两个以字符串形式表示的非负整数 num1num2,要求返回它们的和,结果同样用字符串表示。

题目明示了两条规则:不能使用任何内建的大整数库(如 BigInteger),也不能把输入直接转换成整数处理。这不是可以绕开的细节,而是本题的考点本身——字符串长度可以达到上万位,远超 long 等原生整数类型的表示范围,直接转换在大用例上必然溢出或抛异常。

边界上要注意三点:两个字符串的长度可能相差悬殊,短的一方高位天然缺失;最高位相加后可能再产生一次进位,导致结果比较长的那个输入还多一位;输入保证除 "0" 本身外没有前导零,所以输出不需要额外去零。

解法:双指针模拟竖式加法

核心思路

从两个字符串末尾开始模拟竖式加法。每轮计算对应数字与进位之和,记录个位并更新进位;结果按低位到高位生成,最后反转。

解题步骤

  • ij 指向两个字符串的末位,初始化 carry = 0
  • 当任一字符串还有数字或仍有进位时继续循环。
  • 将未越界的当前数字与 carry 相加,追加 sum % 10,再更新 carry = sum / 10
  • 反转结果并返回。

代码实现

class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder builder = new StringBuilder();
        int i = num1.length() - 1;
        int j = num2.length() - 1;
        int carry = 0;

        while (i >= 0 || j >= 0 || carry > 0) {
            int sum = carry;
            if (i >= 0) {
                sum += num1.charAt(i) - '0';
                i--;
            }
            if (j >= 0) {
                sum += num2.charAt(j) - '0';
                j--;
            }

            builder.append(sum % 10);
            carry = sum / 10;
        }

        return builder.reverse().toString();
    }
}
func addStrings(num1 string, num2 string) string {
    res := make([]byte, 0)
    i := len(num1) - 1
    j := len(num2) - 1
    carry := 0

    for i >= 0 || j >= 0 || carry > 0 {
        sum := carry
        if i >= 0 {
            sum += int(num1[i] - '0')
            i--
        }
        if j >= 0 {
            sum += int(num2[j] - '0')
            j--
        }

        res = append(res, byte(sum%10)+'0')
        carry = sum / 10
    }

    for left, right := 0, len(res)-1; left < right; left, right = left+1, right-1 {
        res[left], res[right] = res[right], res[left]
    }
    return string(res)
}

复杂度分析

  • 时间复杂度:$O(\max(m, n))$,每个数字处理一次,反转结果也是线性操作。
  • 空间复杂度:$O(\max(m, n))$,用于保存结果。

关键点总结

  • 两个指针从末位向前移动,长度不同的一侧按 0 处理。
  • 循环条件必须包含 carry > 0,避免漏掉最高位进位。
  • 尾部追加后统一反转,避免反复在字符串头部插入。

易错点总结

  • 漏掉最终进位,例如 "99" + "1" 应得到 "100"
  • 使用 && 作为循环条件,会丢失较长字符串剩余的高位。
  • 字符转数字要减 '0',数字转字符要加 '0'
  • 忘记反转,会得到低位在前的字符串。

相似题目

题目 难度 考察点
2. 两数相加 中等 同一进位框架搬到链表上,指针推进代替下标
43. 字符串相乘 中等 逐位乘法叠加进位,需按位权预分配结果数组
66. 加一 简单 只加 1 的退化情形,关注全 9 时的扩位
67. 二进制求和 简单 同一模板换成二进制,满 2 才进位
445. 两数相加 II 中等 高位在前的链表加法,需借助栈或先反转
989. 数组形式的整数加法 简单 数字数组与单个整数逐位相加,进位来自加数本身
1073. 负二进制数相加 中等 底数为 -2,进位可能为负,需修正进位规则
LCR 002. 二进制求和 简单 与 67 同题,巩固二进制竖式加法模板