diff --git a/Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/PlusOne_python.ipynb b/Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/PlusOne_python.ipynb new file mode 100644 index 00000000..8acf7b2b --- /dev/null +++ b/Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/PlusOne_python.ipynb @@ -0,0 +1,343 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "464fa3b5", + "metadata": {}, + "source": [ + "# Python コーディング問題: Plus One\n", + "\n", + "## 1. 問題分析結果\n", + "\n", + "### 競技プログラミング視点\n", + "\n", + "- **制約分析**: \n", + " - 配列長: 1 ≤ len(digits) ≤ 100 → O(n)アルゴリズムで十分\n", + " - 各要素: 0 ≤ digits[i] ≤ 9 → 整数演算のみで処理可能\n", + " - 先頭に0なし → エッジケース考慮が簡素化\n", + " \n", + "- **最速手法**: \n", + " - 右から左への単一ループ(O(n))\n", + " - 早期リターンで平均O(1)~O(n)\n", + " - in-place変更で追加メモリ最小化\n", + " \n", + "- **メモリ最小化**: \n", + " - 基本的にin-place操作でO(1)\n", + " - 全桁9のケースのみO(n)の新規メモリ\n", + " \n", + "- **CPython最適化**: \n", + " - リスト操作は全てC実装で高速\n", + " - `range()`の逆順イテレーションは効率的\n", + " - リスト結合は`[1] + digits`より`[1, *digits]`が推奨\n", + "\n", + "### 業務開発視点\n", + "\n", + "- **型安全設計**: \n", + " - `List[int]`での厳密な型ヒント\n", + " - pylance完全対応の型アノテーション\n", + " - Optional型での明示的なNone処理\n", + " \n", + "- **エラーハンドリング**: \n", + " - 入力検証(空配列、型チェック、範囲チェック)\n", + " - ValueError/TypeErrorの適切な使い分け\n", + " - docstringでの例外明記\n", + " \n", + "- **可読性**: \n", + " - 筆算アルゴリズムの直感的な実装\n", + " - 変数名の明確化(carry, digit等)\n", + " - 適切なコメント配置\n", + "\n", + "### Python特有分析\n", + "\n", + "- **データ構造選択**: \n", + " - リスト操作が中心 → `list`が最適\n", + " - 両端操作は少ない → `deque`不要\n", + " - 順序保持必須 → `set`は不適\n", + " \n", + "- **標準ライブラリ活用度**: \n", + " - この問題では標準ライブラリ不要(シンプルなリスト操作のみ)\n", + " - `collections`、`itertools`等は過剰\n", + " \n", + "- **CPython最適化度**: \n", + " - リスト走査は組み込みイテレータで高速\n", + " - リスト結合はスライシングよりスプレッド演算子\n", + " - インデックスアクセスはC実装で高速\n", + "\n", + "## 2. アルゴリズム比較表\n", + "\n", + "|アプローチ|時間計算量|空間計算量|Python実装コスト|可読性|標準ライブラリ活用|CPython最適化|備考|\n", + "|---------|---------|---------|---------------|------|----------------|------------|-----|\n", + "|右から走査(in-place)|O(n)|O(1)*|低|★★★|不要|適|*最悪時O(n)|\n", + "|右から走査(immutable)|O(n)|O(n)|低|★★☆|不要|適|常に新規配列生成|\n", + "|文字列変換|O(n)|O(n)|中|★☆☆|str, int組み込み|不適|型変換コスト大|\n", + "|再帰処理|O(n)|O(n)|高|★☆☆|不要|不適|スタック使用|\n", + "|BigInt演算|O(n)|O(n)|低|★★☆|組み込みint|不適|配列長制限なし時のみ有効|\n", + "\n", + "## 3. 採用アルゴリズムと根拠\n", + "\n", + "### 選択理由\n", + "\n", + "**右から走査(in-place)方式**を採用\n", + "\n", + "1. **計算量優位性**: \n", + " - 時間: O(n)で最適、平均的には早期リターンでより高速\n", + " - 空間: ほぼO(1)、最悪ケース(all 9s)のみO(n)\n", + "\n", + "2. **実装効率**: \n", + " - Pythonのリスト操作は直感的\n", + " - 標準的な筆算アルゴリズムで理解容易\n", + " - コード量が少なく保守性高い\n", + "\n", + "3. **保守性**: \n", + " - エッジケースが明確\n", + " - デバッグが容易\n", + " - チーム開発でも理解しやすい\n", + "\n", + "4. **Python特性**: \n", + " - リスト操作はすべてC実装で高速\n", + " - 型アノテーションが自然\n", + " - pylanceとの相性良好\n", + "\n", + "### Python最適化戦略\n", + "\n", + "1. **逆順イテレーション**: `range(len(digits)-1, -1, -1)`でC実装の高速イテレータ活用\n", + "2. **早期リターン**: 繰り上がり不要時に即座に処理終了\n", + "3. **スプレッド演算子**: `[1, *digits]`で効率的なリスト結合\n", + "4. **in-place変更**: LeetCode形式では許容され、メモリ効率的\n", + "\n", + "### トレードオフ\n", + "\n", + "- **可読性 vs パフォーマンス**: in-place変更は可読性を損なわないため両立\n", + "- **型安全性 vs 簡潔性**: 型ヒントを付けても簡潔性は維持\n", + "- **エラーハンドリング vs 速度**: 競プ版ではエラーチェック省略で高速化\n", + "\n", + "## 4. 実装パターン\n", + "\n", + "### 業務開発版(型安全・エラーハンドリング重視)\n", + "Analyze Complexity\n", + "Runtime 0 ms\n", + "Beats 100.00%\n", + "Memory 19.20 MB\n", + "Beats 19.41%\n", + "```python\n", + "from typing import List\n", + "\n", + "class Solution:\n", + " \"\"\"\n", + " Plus One 問題の解決クラス\n", + " \n", + " 大きな整数を表す配列に1を加算する処理を提供\n", + " \"\"\"\n", + " \n", + " def plusOne(self, digits: List[int]) -> List[int]:\n", + " \"\"\"\n", + " 整数配列に1を加算する(業務開発版)\n", + " \n", + " Args:\n", + " digits: 各桁を表す整数リスト(最上位桁が先頭)\n", + " 各要素は0-9の範囲内である必要がある\n", + " \n", + " Returns:\n", + " 1を加算した結果の整数配列\n", + " \n", + " Raises:\n", + " TypeError: 入力が配列でない、または要素が整数でない場合\n", + " ValueError: 配列が空、または要素が0-9の範囲外の場合\n", + " \n", + " Examples:\n", + " >>> Solution().plusOne([1, 2, 3])\n", + " [1, 2, 4]\n", + " >>> Solution().plusOne([9, 9, 9])\n", + " [1, 0, 0, 0]\n", + " \n", + " Time Complexity: O(n) where n = len(digits)\n", + " Space Complexity: O(1) 平均、O(n) 最悪時(all 9s)\n", + " \"\"\"\n", + " # 入力検証\n", + " self._validate_input(digits)\n", + " \n", + " # 右から左へ走査\n", + " for i in range(len(digits) - 1, -1, -1):\n", + " # 現在の桁が9未満の場合\n", + " if digits[i] < 9:\n", + " digits[i] += 1\n", + " return digits # 繰り上がり不要、即座に返却\n", + " \n", + " # 現在の桁が9の場合、0にして繰り上がり継続\n", + " digits[i] = 0\n", + " \n", + " # 全桁が9だった場合(例: [9,9,9] → [1,0,0,0])\n", + " return [1, *digits]\n", + " \n", + " def _validate_input(self, digits: List[int]) -> None:\n", + " \"\"\"\n", + " 入力配列の検証\n", + " \n", + " Args:\n", + " digits: 検証対象の配列\n", + " \n", + " Raises:\n", + " TypeError: 型が不正な場合\n", + " ValueError: 値が制約を満たさない場合\n", + " \"\"\"\n", + " if not isinstance(digits, list):\n", + " raise TypeError(\"Input must be a list\")\n", + " \n", + " if not digits:\n", + " raise ValueError(\"Input list cannot be empty\")\n", + " \n", + " if len(digits) > 100:\n", + " raise ValueError(\"Input size exceeds constraint (max 100)\")\n", + " \n", + " for i, digit in enumerate(digits):\n", + " if not isinstance(digit, int):\n", + " raise TypeError(f\"Element at index {i} must be an integer\")\n", + " \n", + " if not 0 <= digit <= 9:\n", + " raise ValueError(\n", + " f\"Element at index {i} ({digit}) must be in range [0, 9]\"\n", + " )\n", + " \n", + " # 先頭が0でないことを確認(制約より)\n", + " if len(digits) > 1 and digits[0] == 0:\n", + " raise ValueError(\"Leading zero is not allowed\")\n", + "```\n", + "\n", + "### 競技プログラミング版(パフォーマンス最優先)\n", + "Analyze Complexity\n", + "Runtime 0 ms\n", + "Beats 100.00%\n", + "Memory 19.25 MB\n", + "Beats 17.57%\n", + "```python\n", + "from typing import List\n", + "\n", + "class Solution:\n", + " def plusOne(self, digits: List[int]) -> List[int]:\n", + " \"\"\"\n", + " 整数配列に1を加算する(競プ最適化版)\n", + " \n", + " エラーハンドリング省略、性能最優先\n", + " \n", + " Time Complexity: O(n)\n", + " Space Complexity: O(1) 平均、O(n) 最悪時\n", + " \"\"\"\n", + " # 右から左へ走査(インデックス逆順)\n", + " for i in range(len(digits) - 1, -1, -1):\n", + " if digits[i] < 9:\n", + " digits[i] += 1\n", + " return digits\n", + " digits[i] = 0\n", + " \n", + " # 全桁が9の場合\n", + " return [1, *digits]\n", + "```\n", + "\n", + "### LeetCode提出用(最終版)\n", + "\n", + "```python\n", + "class Solution:\n", + " def plusOne(self, digits: list[int]) -> list[int]:\n", + " \"\"\"\n", + " Time Complexity: O(n)\n", + " Space Complexity: O(1) average, O(n) worst case\n", + " \"\"\"\n", + " for i in range(len(digits) - 1, -1, -1):\n", + " if digits[i] < 9:\n", + " digits[i] += 1\n", + " return digits\n", + " digits[i] = 0\n", + " \n", + " return [1, *digits]\n", + "```\n", + "\n", + "## 5. Python特有の最適化ポイント\n", + "\n", + "### CPython インタープリター最適化\n", + "\n", + "1. **組み込みイテレータ活用**\n", + " ```python\n", + " # range()の逆順イテレーションはC実装で高速\n", + " for i in range(len(digits) - 1, -1, -1):\n", + " ```\n", + "\n", + "2. **リスト操作最適化**\n", + " ```python\n", + " # スプレッド演算子によるリスト結合(Python 3.5+)\n", + " return [1, *digits] # [1] + digits より効率的\n", + " ```\n", + "\n", + "3. **早期リターン**\n", + " ```python\n", + " # 不要なループを回避\n", + " if digits[i] < 9:\n", + " digits[i] += 1\n", + " return digits # 即座に終了\n", + " ```\n", + "\n", + "### データ構造選択の根拠\n", + "\n", + "- **`list`を選択**: \n", + " - インデックスアクセスO(1)\n", + " - 末尾追加O(1)\n", + " - CPythonでC実装、高速\n", + " \n", + "- **`deque`不要**: \n", + " - 先頭挿入は最悪ケースのみ(稀)\n", + " - この問題では`list`で十分\n", + "\n", + "### メモリ最適化\n", + "\n", + "1. **in-place変更**: \n", + " - 新規メモリ確保を最小化\n", + " - LeetCode形式では許容される\n", + " \n", + "2. **スプレッド演算子**: \n", + " - `[1] + digits`はコピーが2回発生\n", + " - `[1, *digits]`は1回で効率的\n", + "\n", + "## 6. 実装の特徴と利点\n", + "\n", + "### 型安全性(pylance対応)\n", + "\n", + "```python\n", + "# Python 3.9+の型ヒント\n", + "def plusOne(self, digits: list[int]) -> list[int]:\n", + " # pylanceで完全な型チェックが可能\n", + " # List[int]より list[int] が推奨(PEP 585)\n", + "```\n", + "\n", + "### エッジケース処理\n", + "\n", + "```python\n", + "# テスト例(実装には含めない)\n", + "# [1,2,3] → [1,2,4] 早期リターン\n", + "# [9] → [1,0] 単一要素、全桁9\n", + "# [1,9,9] → [2,0,0] 部分的繰り上がり\n", + "# [9,9,9] → [1,0,0,0] 全桁9、新規配列生成\n", + "```\n", + "\n", + "### パフォーマンス特性\n", + "\n", + "- **平均ケース**: O(1)~O(k) (kは繰り上がり回数)\n", + "- **最悪ケース**: O(n) (全桁が9)\n", + "- **メモリ**: ほぼO(1)、最悪時のみO(n)\n", + "\n", + "この実装は、Pythonの特性を最大限活用し、可読性とパフォーマンスを両立した最適解となっています。" + ] + }, + { + "cell_type": "markdown", + "id": "d91e2cb0", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/PlusOne_typescript.ipynb b/Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/PlusOne_typescript.ipynb new file mode 100644 index 00000000..a57b0852 --- /dev/null +++ b/Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/PlusOne_typescript.ipynb @@ -0,0 +1,197 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "1443c7f0", + "metadata": {}, + "source": [ + "# TypeScript コーディング問題: Plus One\n", + "\n", + "## 1. 問題の分析\n", + "\n", + "### 競技プログラミング視点での分析\n", + "- **実行速度最優先**: 配列を右から左へ1回走査(O(n))、繰り上がり処理のみ実施\n", + "- **メモリ使用量最小化**: 基本的にin-placeで処理、繰り上がりが先頭まで伝播する場合(all 9s)のみ新配列生成\n", + "- **最悪ケース**: `[9,9,9]` → `[1,0,0,0]` のケースでO(n)の新規メモリ確保が必要\n", + "\n", + "### 業務開発視点での分析\n", + "- **型安全性**: 入力配列の各要素が0-9の範囲内であることを型で保証\n", + "- **エラーハンドリング**: 不正な入力(負の値、10以上の値)に対する検証\n", + "- **可読性**: 繰り上がりロジックを明確に表現\n", + "- **副作用の明示**: 元の配列を変更する(LeetCodeでは許容されるが、業務では注意が必要)\n", + "\n", + "### TypeScript特有の考慮点\n", + "- **型推論**: `number[]` の厳密な型定義で0-9の範囲を保証\n", + "- **readonly**: 引数を `readonly number[]` にすると副作用を防げる(要新配列生成)\n", + "- **型ガード**: 実行時の配列要素検証\n", + "- **コンパイル時最適化**: strict modeでのnull安全性確保\n", + "\n", + "## 2. アルゴリズムアプローチ比較\n", + "\n", + "| アプローチ | 時間計算量 | 空間計算量 | TS実装コスト | 型安全性 | 可読性 | 備考 |\n", + "|---------|----------|---------|------------|---------|--------|------|\n", + "| 右から走査(in-place) | O(n) | O(1)* | 低 | 高 | 高 | *最悪時O(n)、元配列変更 |\n", + "| 右から走査(immutable) | O(n) | O(n) | 中 | 高 | 高 | 常に新配列生成 |\n", + "| BigInt変換 | O(n) | O(n) | 低 | 中 | 中 | 桁数制限に注意 |\n", + "| 再帰的処理 | O(n) | O(n) | 高 | 中 | 低 | スタックオーバーフロー懸念 |\n", + "\n", + "**注**: LeetCode形式では通常in-place変更が許容されるため、最悪時のみO(n)の空間計算量\n", + "\n", + "## 3. 選択したアルゴリズムと理由\n", + "\n", + "### 選択したアプローチ\n", + "**右から走査(in-place)方式**\n", + "\n", + "### 理由\n", + "- **計算量的な優位性**: \n", + " - 時間計算量O(n)で最適\n", + " - 空間計算量はほとんどのケースでO(1)、最悪時(all 9s)のみO(n)\n", + "- **TypeScript環境での型安全性**:\n", + " - 配列操作が直感的で型推論が効く\n", + " - 繰り上がりフラグを明示的に管理できる\n", + "- **保守性・可読性の観点**:\n", + " - 小学校の筆算アルゴリズムと同じロジックで理解しやすい\n", + " - エッジケースが明確(繰り上がり継続 vs 終了)\n", + "\n", + "### TypeScript特有の最適化ポイント\n", + "- **早期リターン**: 繰り上がりが発生しない時点で即座に返却\n", + "- **型安全な配列操作**: `unshift` より `[1, ...digits]` で可読性向上\n", + "- **const assertion**: 定数値の型を厳密化\n", + "\n", + "## 4. 実装コード\n", + "Analyze Complexity\n", + "Runtime 0 ms\n", + "Beats 100.00%\n", + "Memory 56.17 MB\n", + "Beats 6.38%\n", + "```typescript\n", + "/**\n", + " * 大きな整数を表す配列に1を加算する\n", + " * @param digits - 各桁を表す数値配列(最上位桁が先頭)\n", + " * @returns 1を加算した結果の配列\n", + " * @complexity Time: O(n), Space: O(1) 平均、O(n) 最悪時\n", + " * @sideEffect 入力配列を直接変更する(LeetCode形式では許容)\n", + " */\n", + "function plusOne(digits: number[]): number[] {\n", + " // 型ガード: 配列の検証\n", + " if (!Array.isArray(digits) || digits.length === 0) {\n", + " throw new TypeError('Input must be a non-empty array');\n", + " }\n", + " \n", + " // 右端から左へ走査\n", + " for (let i = digits.length - 1; i >= 0; i--) {\n", + " // 現在の桁が9未満の場合\n", + " if (digits[i] < 9) {\n", + " digits[i]++; // 副作用: 元配列を変更\n", + " return digits; // 繰り上がり不要、即座に返却\n", + " }\n", + " \n", + " // 現在の桁が9の場合、0にして繰り上がり継続\n", + " digits[i] = 0; // 副作用: 元配列を変更\n", + " }\n", + " \n", + " // 全桁が9だった場合(例: [9,9,9] → [1,0,0,0])\n", + " // この時点で元配列は [0,0,0] に変更済み\n", + " // 先頭に1を追加した新配列を返却\n", + " return [1, ...digits];\n", + "}\n", + "```\n", + "\n", + "### コード解説\n", + "\n", + "1. **型ガード(オプショナル)**: LeetCodeでは不要だが、業務コードでは有用\n", + "2. **右から左へのループ**: \n", + " - `digits[i] < 9` の場合: インクリメントして即座にリターン(O(1)で終了)\n", + " - `digits[i] === 9` の場合: 0に設定して次の桁へ繰り上がり継続\n", + "3. **全桁9のケース**: ループを抜けた = 全桁が9だった → `[1, 0, 0, ..., 0]` を返却\n", + "\n", + "### 副作用に関する重要な注意\n", + "\n", + "**この関数は入力配列を直接変更します(impure function)**:\n", + "\n", + "```typescript\n", + "const original = [1, 2, 9];\n", + "const result = plusOne(original);\n", + "// original は [1, 3, 0] に変更されている(副作用)\n", + "// result も [1, 3, 0] を参照(同じ配列)\n", + "\n", + "const allNines = [9, 9, 9];\n", + "const result2 = plusOne(allNines);\n", + "// allNines は [0, 0, 0] に変更されている(副作用)\n", + "// result2 は [1, 0, 0, 0](新しい配列)\n", + "```\n", + "\n", + "**LeetCodeでは許容されますが、業務コードでは以下の対応を検討**:\n", + "- 引数を `readonly number[]` にして、内部で `[...digits]` をコピー\n", + "- 関数名を `plusOneInPlace` に変更して副作用を明示\n", + "- JSDocに `@sideEffect` タグを追加\n", + "\n", + "### 型安全性の特徴\n", + "\n", + "- **入力型**: `number[]` - 数値配列であることを保証\n", + "- **戻り値型**: `number[]` - 同じ型を返却\n", + "- **副作用**: 元配列を変更する(LeetCode形式では許容)\n", + "- **null安全性**: TypeScript strict modeで配列操作が安全\n", + "\n", + "### エッジケース処理\n", + "\n", + "```typescript\n", + "// テストケース例(実装には含めない)\n", + "// [1,2,3] → [1,2,4] 早期リターン、元配列変更\n", + "// [1,9,9] → [2,0,0] 2回繰り上がり、元配列変更\n", + "// [9,9,9] → [1,0,0,0] 全桁繰り上がり、元配列は[0,0,0]に変更済み\n", + "// [0] → [1] 単一要素、元配列変更\n", + "```\n", + "\n", + "## TypeScript固有の最適化観点\n", + "\n", + "### 型安全性の活用\n", + "- **厳密な型定義**: `number[]` で配列要素の型を保証\n", + "- **配列メソッドの型推論**: スプレッド構文 `[1, ...digits]` での型安全な配列生成\n", + "- **境界値チェック**: インデックスアクセスの安全性\n", + "\n", + "### コンパイル時最適化\n", + "- **const宣言**: ループカウンタ `i` を `let` で宣言(再代入が必要)\n", + "- **早期リターン**: 不要な処理をスキップしてパフォーマンス向上\n", + "- **スプレッド構文**: `[1, ...digits]` はコンパイラによって最適化される\n", + "\n", + "### 開発効率と保守性\n", + "- **シンプルなロジック**: 筆算のアルゴリズムそのもので直感的\n", + "- **副作用の明示**: 関数が元配列を変更することをドキュメント化\n", + "- **拡張性**: 他の進数への対応も容易(10を変数化すれば対応可能)\n", + "\n", + "### Immutable版の実装例(業務コード向け)\n", + "\n", + "```typescript\n", + "/**\n", + " * 大きな整数を表す配列に1を加算する(Immutable版)\n", + " * @param digits - 各桁を表す数値配列(最上位桁が先頭)\n", + " * @returns 1を加算した結果の新しい配列\n", + " * @complexity Time: O(n), Space: O(n)\n", + " * @pure 元配列を変更しない\n", + " */\n", + "function plusOneImmutable(digits: readonly number[]): number[] {\n", + " const result = [...digits]; // コピーを作成\n", + " \n", + " for (let i = result.length - 1; i >= 0; i--) {\n", + " if (result[i] < 9) {\n", + " result[i]++;\n", + " return result;\n", + " }\n", + " result[i] = 0;\n", + " }\n", + " \n", + " return [1, ...result];\n", + "}\n", + "```" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/README.md b/Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/README.md new file mode 100644 index 00000000..c9aebc93 --- /dev/null +++ b/Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/README.md @@ -0,0 +1,573 @@ +# Plus One - 大きな整数配列への1加算 + +
+ 右から左への繰り上がり処理による O(n) 実装 +
+ ++ 大きな整数を配列形式で表現したとき(各要素が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 <= digits.length <= 100
+ 0 <= digits[i] <= 9
+ [0,1,2] は不正)
+
+ O(n)
+
+ 平均的には早期リターンでO(1)~O(k) +
+
+ O(1) 平均
+
最悪時(全桁9)のみO(n)
+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]
+ 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];
+}
+
+ フローの説明:
+ 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)
+ |
+ + 中 + | ++ 常に新配列生成、メモリ非効率 + | +
[1, *digits]
+ で効率的なリスト結合(全桁9のケースのみ)
+