大家好,我是 @负雪明烛

求加法」是个系列题目,相关题目见文末。

解题方法:模拟法

十进制加法

我们先回顾一下十进制加法的计算过程:
加法.001.jpeg
使用「竖式」计算十进制的加法的方式:

  1. 两个「加数」的右端对齐;
  2. 从最右侧开始,依次计算对应的两位数字的和。如果和大于等于 10,则把和的个位数字计入结果,并向前面进位。
  3. 依次向左计算对应位置两位数字的和,如果有进位需要加上进位。如果和大于等于 10,仍然把和的个位数字计入结果,并向前面进位。
  4. 当两个「加数」的每个位置都计算完成,如果最后仍有进位,需要把进位数字保留到计算结果中。

    本题解法

本题给出的数字是 digits 以列表形式给出每一位数字,让我们对 digits 加一。

其实就是模拟十进制加法的过程:两个加数分别是 digitis 和 $1$ 。

直接按照上面的十进制加法的模拟思路进行计算就可以。

在实现中需要注意的有:

  1. 不可以把 digits 先转化成 int 型数字再求和,因为可能溢出
  2. 另一个「加数」是 adder ,初始化为 $1$ ,以后都是 $0$;
  3. 两个「加数」的长度可能不同;
  4. 在最后,如果进位 carry 不为 0,那么最后需要计算进位

方法:循环

循环的思想比较朴素,就是倒序遍历 digits 的每个元素,与另一个加数 adder 和 进位 carry相加的过程。

代码中的巧妙之处:

  1. while (p1 >= 0 || adder > 0 || carry > 0)含义:
    1. digitsadder 只要有一个没遍历完,那么就继续遍历;
    2. 如果字符串 digitsadder 都遍历完了,但是最后留下的进位 carry != 0,那么需要把进位也保留到结果中。
  2. 取当前位置的数字的时候,如果 digits 已经遍历完了(即 $p1 <= 0$),则认为 digits 的对应位置是 $0$ 。

Java / C++ / Python 三种语言的代码:

  1. class Solution {
  2. public int[] plusOne(int[] digits) {
  3. int N = digits.length;
  4. List<Integer> resultList = new ArrayList<>();
  5. int p1 = N - 1;
  6. int carry = 0;
  7. int adder = 1;
  8. while (p1 >= 0 || adder > 0 || carry > 0) {
  9. int num = p1 >= 0 ? digits[p1] : 0;
  10. int sum = num + adder + carry;
  11. carry = sum >= 10 ? 1 : 0;
  12. sum = sum >= 10 ? sum - 10 : sum;
  13. resultList.add(sum);
  14. p1 --;
  15. adder = 0;
  16. }
  17. int[] res = new int[resultList.size()];
  18. for (int i = 0; i < resultList.size(); ++i) {
  19. res[i] = resultList.get(resultList.size() - i - 1);
  20. }
  21. return res;
  22. }
  23. }
  1. class Solution {
  2. public:
  3. vector<int> plusOne(vector<int>& digits) {
  4. const int N = digits.size();
  5. vector<int> res;
  6. int p1 = N - 1;
  7. int carry = 0;
  8. int adder = 1;
  9. while (p1 >= 0 || adder > 0 || carry > 0) {
  10. int num = p1 >= 0 ? digits[p1] : 0;
  11. int sum = num + adder + carry;
  12. carry = sum >= 10 ? 1 : 0;
  13. sum = sum >= 10 ? sum - 10 : sum;
  14. res.push_back(sum);
  15. p1 --;
  16. adder = 0;
  17. }
  18. reverse(res.begin(), res.end());
  19. return res;
  20. }
  21. };
class Solution(object):
    def plusOne(self, digits):
        N = len(digits)
        res = []
        adder = 1
        carry = 0
        p1 = N - 1
        while p1 >= 0 or adder > 0 or carry > 0:
            num = digits[p1] if p1 >= 0 else 0
            sum = num + adder + carry
            carry = 1 if sum >= 10 else 0
            sum = sum - 10 if sum >= 10 else sum
            res.append(sum)
            p1 -= 1
            adder = 0
        return res[::-1]

复杂度分析:

  • 时间复杂度:$O(max(N))$,$N$ 是 digits的长度;
  • 空间复杂度:$O(1)$,只使用了常数的空间。

类似题目

看完本题解本题,你可以解决以下题目:

总结

  1. 加法」系列题目都不难,其实就是「列竖式」模拟法
  2. 需要注意的是 while循环结束条件,注意遍历两个「加数」不要越界,以及考虑进位。

——
我是 @负雪明烛 ,刷算法题 1000 多道,写了 1000 多篇算法题解,收获阅读量 300 万。
关注我,你将不会错过我的精彩动画题解、面试题分享、组队刷题活动,进入主页 @负雪明烛 右侧有刷题组织,从此刷题不再孤单。