题目描述

✅ 989. 数组形式的整数加法

image-20260928223520500

image-20260928223520509

题意分析

数组 num 从高位到低位保存一个整数的十进制数字,要求返回它与 k 相加后的数字数组。数组最多有一万位,不能先把它整体转换成固定宽度整数,但每一位的加法仍然可以直接计算。

解法:从后向前模拟

核心思路

[!blue]

按竖式加法从个位开始处理。用 i 指向 num 尚未处理的最低位;k % 10 取得另一个加数的当前最低位,k /= 10 去掉这一位;carry 保存上一轮从低位传来的进位。

每轮令 sum 等于两边当前数字与 carry 之和。某一边已经没有数字时,就把它在这一位上的贡献视为 $0$。当前结果位是 sum % 10,传给下一位的进位是 sum / 10。两边数字最多各为 $9$,进位最多为 $1$,所以每轮局部计算都很小,不受整个整数长度影响。

处理完一轮后,结果中已经确定的低位无需再改变,i、剩余 k 和 carry 则描述所有尚未处理的高位。因此循环必须在“数组还有数字、k 还有数字、还有进位”任一条件成立时继续。即使两个加数都耗尽,最后的进位也可能单独形成一位。

数字按从低位到高位的顺序产生,先追加到列表尾部,最后统一反转即可得到题目要求的高位在前顺序。无需不断向列表头部插入,也不会改变原数组。

解题步骤

  1. 初始化 i = num.length - 1、carry = 0 和结果列表。
  2. 当 i >= 0 || k > 0 || carry > 0 时,以 carry 为本轮和的初值,再加入两边仍存在的当前数字。
  3. 将 sum % 10 追加到结果,令 carry = sum / 10,已使用的数组位置和 k 的个位都不再保留。
  4. 循环结束后反转结果并返回。

代码实现

class Solution {
    public List<Integer> addToArrayForm(int[] num, int k) {
        List<Integer> res = new ArrayList<>();
        int i = num.length - 1;
        int carry = 0;

        // 两边尚有数字或仍有进位时,都要继续处理。
        while (i >= 0 || k > 0 || carry > 0) {
            int sum = carry;

            if (i >= 0) {
                sum += num[i--];
            }

            if (k > 0) {
                sum += k % 10;
                k /= 10;
            }

            res.add(sum % 10);
            carry = sum / 10;
        }

        // 按低位到高位生成,最后反转为正常次序。
        Collections.reverse(res);

        return res;
    }
}
func addToArrayForm(num []int, k int) []int {
    res := make([]int, 0)
    i := len(num) - 1
    carry := 0

    // 两边尚有数字或仍有进位时,都要继续处理。
    for i >= 0 || k > 0 || carry > 0 {
        sum := carry
        if i >= 0 {
            sum += num[i]
            i--
        }
        if k > 0 {
            sum += k % 10
            k /= 10
        }

        res = append(res, sum%10)
        carry = sum / 10
    }

    // 按低位到高位生成,最后反转为正常次序。
    for l, r := 0, len(res)-1; l < r; l, r = l+1, r-1 {
        res[l], res[r] = res[r], res[l]
    }

    return res
}

复杂度分析

  • 时间复杂度:$O(\max(n,d))$,其中 n 是数组长度,d 是 k 的十进制位数;每轮处理一位,最终最多再处理一次进位,反转也是线性时间。
  • 空间复杂度:除返回结果外为 $O(1)$;结果最多有 $\max(n,d)+1$ 位。

关键点总结

[!green]

  • 循环条件是多个来源的或,不是要求两边都有剩余位。
  • 最后进位可能使结果增加一位。

易错点总结

[!yellow]

  • 只循环数组长度,会漏掉 k 更高位或最终进位。
  • 先把 sum 覆盖为除十的商,再从 sum 取个位,会丢失本轮原始和的个位。
  • 结果不反转,会把低位顺序直接返回。

相似题目

题目 难度 关联与区别
66. 加一 简单 把固定加1推广为加整数k,仍从数组低位开始处理进位。
415. 字符串相加 简单 同样模拟十进制加法,本题一个加数是数字数组,另一个可边取余边消耗。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2021/59170359
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!