LeetCode 66. 加一
问题描述
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位,数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
示例:
示例 1:
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。
加 1 后得到 123 + 1 = 124。
因此,结果应该是 [1,2,4]。
示例 2:
输入:digits = [4,3,2,1]
输出:[4,3,2,2]
解释:输入数组表示数字 4321。
加 1 后得到 4321 + 1 = 4322。
因此,结果应该是 [4,3,2,2]。
示例 3:
输入:digits = [9]
输出:[1,0]
解释:输入数组表示数字 9。
加 1 得到了 9 + 1 = 10。
因此,结果应该是 [1,0]。
算法思路
逆序遍历模拟加法:
- 从末位开始加一:
- 最后一位加一,判断是否产生进位
- 若无进位(值<10),直接返回结果
- 若产生进位(值=10),当前位设为0,进位标志置为1
- 处理进位传递:
- 向前遍历,每位加上进位值
- 若进位消失则终止遍历
- 处理最高位进位:
- 若遍历结束仍有进位,在数组最前面添加元素1
代码实现
class Solution {
public int[] plusOne(int[] digits) {
int n = digits.length;
int carry = 1; // 初始进位为1(相当于加一操作)
// 逆序遍历处理进位
for (int i = n - 1; i >= 0; i--) {
int sum = digits[i] + carry;
digits[i] = sum % 10; // 更新当前位
carry = sum / 10; // 计算新进位
// 无进位时提前结束
if (carry == 0) {
return digits;
}
}
// 处理最高位进位
if (carry == 1) {
int[] newDigits = new int[n + 1];
newDigits[0] = 1; // 最高位置1
// 其余位默认为0(System.arraycopy可省略)
return newDigits;
}
return digits;
}
}
算法分析
- 时间复杂度:O(n)
- 最坏情况需遍历整个数组
(全9的情况)
- 最坏情况需遍历整个数组
- 空间复杂度:O(1) 或 O(n)
- 无进位时:O(1)(原地修改)
- 有进位时:O(n)(创建新数组)
关键点
-
进位处理:
- 使用
carry
记录进位值 sum % 10
得到当前位结果sum / 10
得到新的进位值
- 使用
-
提前终止:
- 当进位消失时立即返回结果
- 避免不必要遍历
-
最高位进位:
- 创建长度+1的新数组
- 首位设为1,其余位自动初始化为0
算法过程
示例1:digits = [1,2,3]
1. 末位加一:3+1=4 → [1,2,4]
2. 无进位 → 返回[1,2,4]
示例2:digits = [9,9,9]
1. 末位加一:9+1=10 → [9,9,0] carry=1
2. 中间位:9+1=10 → [9,0,0] carry=1
3. 首位:9+1=10 → [0,0,0] carry=1
4. 创建新数组:[1,0,0,0]
边界情况处理
- 全9数组:
[9,9,9] → [1,0,0,0]
- 中间进位:
[4,9,9] → [5,0,0]
- 无进位:
[1,2,3] → [1,2,4]
- 单元素进位:
[9] → [1,0]
优化
- 减少循环:
// 优化版本:合并循环与终止条件 for (int i = n - 1; i >= 0; i--) { if (digits[i] < 9) { digits[i]++; return digits; } digits[i] = 0; // 9变为0 } // 全9情况单独处理 int[] newDigits = new int[n + 1]; newDigits[0] = 1; return newDigits;
测试用例
public static void main(String[] args) {
Solution solution = new Solution();
// 测试用例1:无进位
int[] digits1 = {1,2,3};
System.out.println("Test 1: " + Arrays.toString(solution.plusOne(digits1)));
// [1,2,4]
// 测试用例2:末位进位
int[] digits2 = {4,3,9};
System.out.println("Test 2: " + Arrays.toString(solution.plusOne(digits2)));
// [4,4,0]
// 测试用例3:连续进位
int[] digits3 = {8,9,9};
System.out.println("Test 3: " + Arrays.toString(solution.plusOne(digits3)));
// [9,0,0]
// 测试用例4:全9数组
int[] digits4 = {9,9,9};
System.out.println("Test 4: " + Arrays.toString(solution.plusOne(digits4)));
// [1,0,0,0]
// 测试用例5:单元素进位
int[] digits5 = {9};
System.out.println("Test 5: " + Arrays.toString(solution.plusOne(digits5)));
// [1,0]
// 测试用例6:含0数组
int[] digits6 = {0};
System.out.println("Test 6: " + Arrays.toString(solution.plusOne(digits6)));
// [1]
}
常见问题
-
为什么需要单独处理全9情况?
全9时每位都会进位,最终需要增加数组长度(如999→1000)。 -
空间复杂度何时为O(n)?
仅当最高位产生进位时(概率较低),多数情况下是O(1)。 -
能否原地修改数组?
无进位时可原地修改,有进位时必须创建新数组。 -
如何处理大整数?
本题限定数组长度较小(≤100),无需特殊处理。