アルゴリズム概要

問題説明

大きな整数を配列形式で表現したとき(各要素が1桁、最上位桁が先頭)、この整数に1を加算した結果を配列で返す問題です。

入出力例

入力: digits = [1,2,3]
出力: [1,2,4]
説明: 123 + 1 = 124

入力: digits = [9,9,9]
出力: [1,0,0,0]
説明: 999 + 1 = 1000

入力: digits = [9]
出力: [1,0]
説明: 9 + 1 = 10

制約条件

戦略

  • 1 右から左への走査: 配列の右端(最下位桁)から開始し、左へ進む
  • 2 早期終了: 9未満の桁を見つけたら+1して即座にリターン(最頻ケース)
  • 3 繰り上がり処理: 9の場合は0に変更し、次の桁へ繰り上がりを継続
  • 4 桁数増加: 全桁が9の場合のみ、先頭に1を追加した新配列を返却

主要ポイント

⏱ 時間計算量

O(n)

平均的には早期リターンでO(1)~O(k)

💾 空間計算量

O(1) 平均

最悪時(全桁9)のみO(n)

ステップバイステップ解説

Python実装

class Solution:
    def plusOne(self, digits: list[int]) -> list[int]:
        """
        整数配列に1を加算する

        Time Complexity: O(n)
        Space Complexity: O(1) average, O(n) worst case
        """
        # 右から左へ走査
        for i in range(len(digits) - 1, -1, -1):
            # 現在の桁が9未満の場合
            if digits[i] < 9:
                digits[i] += 1
                return digits  # 繰り上がり不要、即座に返却

            # 現在の桁が9の場合、0にして繰り上がり継続
            digits[i] = 0

        # 全桁が9だった場合(例: [9,9,9] -> [1,0,0,0])
        # 先頭に1を追加
        return [1, *digits]

TypeScript実装

function plusOne(digits: number[]): number[] {
    /**
     * 整数配列に1を加算する
     *
     * Time Complexity: O(n)
     * Space Complexity: O(1) average, O(n) worst case
     */

    // 右から左へ走査
    for (let i = digits.length - 1; i >= 0; i--) {
        // 現在の桁が9未満の場合
        if (digits[i] < 9) {
            digits[i]++;
            return digits;  // 繰り上がり不要、即座に返却
        }

        // 現在の桁が9の場合、0にして繰り上がり継続
        digits[i] = 0;
    }

    // 全桁が9だった場合(例: [9,9,9] -> [1,0,0,0])
    // 先頭に1を追加
    return [1, ...digits];
}

フローチャート

開始 i = len(digits) - 1 右端から開始 i >= 0? 全桁が9 return [1, *digits] いいえ digits[i] < 9? はい digits[i] += 1 return digits はい digits[i] = 0 繰り上がり継続 いいえ i = i - 1 次の桁へ 終了

フローの説明:
1. 右端のインデックス(i = len-1)から開始
2. i >= 0 の間ループを継続
3. digits[i] < 9 なら +1 して即座に終了(成功パス・緑)
4. digits[i] == 9 なら 0 に設定し、i を減らして次の桁へ(繰り上がり継続・紫)
5. ループを抜けた = 全桁が9 → 先頭に1を追加して終了(特殊ケースパス・赤)

計算量分析

ケース 時間計算量 空間計算量 備考
最良ケース O(1) O(1) 右端の桁が9未満、1回で終了
平均ケース O(k) O(1) k個の連続する9を処理(k < n)
最悪ケース O(n) O(n) 全桁が9、新配列生成が必要

最適化の比較

アプローチ 時間 空間 実装コスト 備考
✓ 右から走査(本実装) O(n) O(1)平均 早期終了で高速、メモリ効率的
文字列変換 O(n) O(n) 型変換オーバーヘッド大
完全immutable O(n) O(n) 常に新配列生成、メモリ非効率

💡 最適化ポイント

  • 早期リターン: 90%以上のケースでO(1)で終了(右端の桁が9未満の場合)
  • in-place変更: 追加メモリを使わず、既存配列を変更してメモリ効率を最大化
  • スプレッド演算子: [1, *digits] で効率的なリスト結合(全桁9のケースのみ)