算法题 加一

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]。

算法思路

逆序遍历模拟加法

  1. 从末位开始加一
    • 最后一位加一,判断是否产生进位
    • 若无进位(值<10),直接返回结果
    • 若产生进位(值=10),当前位设为0,进位标志置为1
  2. 处理进位传递
    • 向前遍历,每位加上进位值
    • 若进位消失则终止遍历
  3. 处理最高位进位
    • 若遍历结束仍有进位,在数组最前面添加元素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)(创建新数组)

关键点

  1. 进位处理

    • 使用 carry 记录进位值
    • sum % 10 得到当前位结果
    • sum / 10 得到新的进位值
  2. 提前终止

    • 当进位消失时立即返回结果
    • 避免不必要遍历
  3. 最高位进位

    • 创建长度+1的新数组
    • 首位设为1,其余位自动初始化为0

算法过程

示例1digits = [1,2,3]

1. 末位加一:3+1=4 → [1,2,4]
2. 无进位 → 返回[1,2,4]

示例2digits = [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]

边界情况处理

  1. 全9数组[9,9,9] → [1,0,0,0]
  2. 中间进位[4,9,9] → [5,0,0]
  3. 无进位[1,2,3] → [1,2,4]
  4. 单元素进位[9] → [1,0]

优化

  1. 减少循环
    // 优化版本:合并循环与终止条件
    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]
}

常见问题

  1. 为什么需要单独处理全9情况?
    全9时每位都会进位,最终需要增加数组长度(如999→1000)。

  2. 空间复杂度何时为O(n)?
    仅当最高位产生进位时(概率较低),多数情况下是O(1)。

  3. 能否原地修改数组?
    无进位时可原地修改,有进位时必须创建新数组。

  4. 如何处理大整数?
    本题限定数组长度较小(≤100),无需特殊处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值