LeetCode 66. 加一
本节目标
从最低位反向传播进位,并在不再进位时立即返回。
这道题承接模拟、递推与边界:把进位看作从最低位向高位传播的状态,并单独处理全进位的边界。
题意与约束
给定一个非空数组 digits,其中每个元素是一位十进制数字,数组按从最高位到最低位表示一个非负整数。将这个整数加一后,返回同样形式的数字数组。
1 <= digits.length <= 100- 每个
digits[i]都在0到9之间。 - 除数字
0本身外,最高位不会是0。
从最低位传播进位
加一只会先影响最低位,所以从数组末尾反向扫描。遇到小于 9 的数字时,直接加一即可;更高位和已经处理的后缀都不需要再改动。
若当前位是 9,它加一后应写成 0,同时进位继续向左传播。循环持续时,已经处理的后缀恰好全为 0;这正是进位仍未停止的状态。
为什么可以提前返回
一旦遇到小于 9 的数字,给它加一便消除了进位。更高位从未修改,后缀已经在之前逐位改为正确的 0,整个数组已经是答案,因此可以立刻返回。
例如 [4, 3, 2, 1] 从末位开始就能返回 [4, 3, 2, 2],不必扫描其余三位。
全是 9 时发生什么
[9, 9] 会依次变成 [9, 0]、[0, 0],扫描结束后仍有一个进位。此时原数组已经是所需长度的全零数组,在最前面插入 1 即得到 [1, 0, 0]。
这也是唯一需要增加数组长度的情况。
代码实现
两份源码都从最低位反向处理;仅在进位停止时提前返回,全部为 9 时再构造新的最高位。
- C++
- Python
C++17
#include <vector>
using namespace std;
class Solution {
public:
vector<int> plusOne(vector<int>& digits) {
for (int i = static_cast<int>(digits.size()) - 1; i >= 0; i--) {
if (digits[i] < 9) {
digits[i]++;
return digits;
}
digits[i] = 0;
}
digits.insert(digits.begin(), 1);
return digits;
}
};
Python 3
class Solution:
def plusOne(self, digits: list[int]) -> list[int]:
for i in range(len(digits) - 1, -1, -1):
if digits[i] < 9:
digits[i] += 1
return digits
digits[i] = 0
return [1] + digits
复杂度分析
- 最好情况:最低位小于
9,只处理一位,时间复杂度为O(1)。 - 最坏情况:所有数字都是
9,需要扫描整个数组,时间复杂度为O(n)。 - 除返回数组本身外只使用常数变量,额外空间复杂度为
O(1)。
易错点
- 从最高位开始处理,无法自然表达进位方向。
- 把
9加一后保留为10,忘记当前位应写为0。 - 所有数字都是
9时只返回全零数组,遗漏新增最高位的1。 - 遇到小于
9的数字后继续改动更高位,而不是立即返回。
模式迁移
数位加法、大整数模拟、链表表示的数字相加都遵循同一个方向:从最低位读取旧值,写回当前位,并把是否继续进位交给更高位。若进位已经消失,应优先识别可以提前结束的位置。