From 1d9db0612a3b5e531e083e7041185d66d74b3dcb Mon Sep 17 00:00:00 2001 From: myoshizumi Date: Wed, 11 Mar 2026 10:03:53 +0900 Subject: [PATCH 01/11] feat: add Claude 4.6 extended solution for LeetCode 83 (Remove Duplicates from Sorted List) --- .../Claude 4.6 extended/README.md | 371 +++++ .../Claude 4.6 extended/README_React.html | 1277 +++++++++++++++++ ...move_Duplicates_from_Sorted_List_Python.md | 191 +++ ...Remove_Duplicates_from_Sorted_List_Rust.md | 190 +++ ..._Duplicates_from_Sorted_List_Typescript.md | 163 +++ .../Claude 4.6 extended/README_React.html | 1277 +++++++++++++++++ public/index.html | 10 +- 7 files changed, 3475 insertions(+), 4 deletions(-) create mode 100644 Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README.md create mode 100644 Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html create mode 100644 Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Python.md create mode 100644 Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Rust.md create mode 100644 Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Typescript.md create mode 100644 public/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html diff --git a/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README.md b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README.md new file mode 100644 index 00000000..02c65683 --- /dev/null +++ b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README.md @@ -0,0 +1,371 @@ +# Remove Duplicates from Sorted List - In-place Pointer Traversal + +## 目次(Table of Contents) + +- [概要](#overview) +- [アルゴリズム要点 TL;DR](#tldr) +- [図解](#figures) +- [正しさのスケッチ](#correctness) +- [計算量](#complexity) +- [Python 実装](#impl) +- [CPython 最適化ポイント](#cpython) +- [エッジケースと検証観点](#edgecases) +- [FAQ](#faq) + +--- + +

概要

+ +### 問題要約 + +**LeetCode #83 — Remove Duplicates from Sorted List** + +ソート済み単方向連結リストの先頭ノード `head` を受け取り、**各要素がちょうど 1 回だけ現れる**ようにリストをインプレースで変更して返す。 + +### 要件 + +| 項目 | 内容 | +| ---------- | ---------------------------------------------------- | +| 入力 | `head: Optional[ListNode]`(ソート済み連結リスト) | +| 出力 | `Optional[ListNode]`(重複除去済み、同じ先頭ノード) | +| ノード数 | 0 〜 300 | +| 値の範囲 | −100 〜 100 | +| ソート保証 | 昇順ソート済み(重複は必ず**隣接**する) | +| 安定性 | 元の相対順序を保持 | +| 副作用 | `next` ポインタをインプレースで変更(Pure ではない) | + +--- + +

アルゴリズム要点(TL;DR)

+ +- **戦略**: ソート済みであることを活かし、**隣接する重複を 1 パスで除去**する +- **データ構造**: `current` ポインタ 1 本のみ(追加構造なし) +- **操作**: `current.val == current.next.val` の間 `current.next` を読み飛ばし続け、異なった時点で `current` を前進 +- **計算量**: Time `O(n)` / Space `O(1)` +- **メモリ**: スタック変数 `current` と `nxt` のみ。新規ノード生成ゼロ +- **CPython 最適化**: `current.next` の繰り返し属性アクセスをローカル変数 `nxt` にキャッシュして `LOAD_ATTR` を削減 + +--- + +

図解

+ +### フローチャート + +```mermaid +flowchart TD + Start[Start deleteDuplicates] --> Guard{head is None or head.next is None} + Guard -- Yes --> RetHead[Return head as is] + Guard -- No --> Init[current = head] + Init --> LoopCond{current.next is not None} + LoopCond -- No --> RetHead2[Return head] + LoopCond -- Yes --> Cache[nxt = current.next] + Cache --> Dup{current.val == nxt.val} + Dup -- Yes --> Skip[current.next = nxt.next] + Skip --> LoopCond + Dup -- No --> Advance[current = nxt] + Advance --> LoopCond +``` + +> `current` は重複が続く限り**移動しない**点がポイント。`nxt` をスキップしても同値が連続する可能性があるため、読み飛ばし後に再度チェックする。 + +--- + +### データフロー図(具体例) + +```mermaid +graph LR + subgraph Input + N1[1] --> N2[1] + N2 --> N3[2] + N3 --> N4[3] + N4 --> N5[3] + N5 --> NullA[None] + end + subgraph Step1 + S1_1[1] --> S1_3[2] + S1_3 --> S1_4[3] + S1_4 --> S1_5[3] + S1_5 --> NullB[None] + end + subgraph Step2 + S2_1[1] --> S2_3[2] + S2_3 --> S2_4[3] + S2_4 --> NullC[None] + end + subgraph Output + O1[1] --> O3[2] + O3 --> O4[3] + O4 --> NullD[None] + end + Input -- skip dup 1 --> Step1 + Step1 -- advance cur --> Step2 + Step2 -- skip dup 3 --> Output +``` + +> 各ステップで `current.next` の接続先を付け替えることで、中間ノードをリストから切り離す。切り離されたノードは Python の GC が自動回収する。 + +--- + +### ASCII ポインタ操作図 + +``` +【初期状態】 + [1] → [1] → [2] → [3] → [3] → None + ↑ + cur + +Step 1: cur.val(1) == nxt.val(1) → nxt をスキップ + cur.next = nxt.next + [1] ──────→ [2] → [3] → [3] → None + ↑ + cur ※ cur は移動しない + +Step 2: cur.val(1) != nxt.val(2) → cur を前進 + [1] → [2] → [3] → [3] → None + ↑ + cur + +Step 3: cur.val(2) != nxt.val(3) → cur を前進 + [1] → [2] → [3] → [3] → None + ↑ + cur + +Step 4: cur.val(3) == nxt.val(3) → nxt をスキップ + [1] → [2] → [3] → None + ↑ + cur + +Step 5: cur.next is None → ループ終了 +出力: [1] → [2] → [3] → None ✅ +``` + +--- + +

正しさのスケッチ

+ +### 不変条件 + +> ループの各反復開始時点で、`head` から `current`(含む)までの部分列には重複がない。 + +| 条件 | 説明 | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------- | +| **初期化** | `current = head` の時点で部分列は長さ 1 → 自明に重複なし | +| **維持** | `current.val == nxt.val` なら `nxt` をスキップ(不変条件を保ちつつ次を確認)。異なれば `current` を前進(不変条件は維持される) | +| **終了** | `current.next is None` でループを抜けると、リスト全体で不変条件が成立 | + +### 網羅性 + +- 重複を検出するたびに `next` を付け替え → 検出漏れなし(ソート済みなので隣接比較で十分) +- `current` が前進するのは値が異なる場合のみ → 3連続以上の重複も正しく処理される + +### 終了性 + +- `current` は前進するか、`next` ポインタが短縮されるかのいずれか +- リストは有限長 → 必ず `current.next is None` に到達してループ終了 + +--- + +

計算量

+ +| 指標 | 値 | 理由 | +| -------------- | ------ | ------------------------------------------------------- | +| **時間計算量** | `O(n)` | 各ノードを最大 1 回しか走査しない | +| **空間計算量** | `O(1)` | スタック変数 `current` / `nxt` のみ。ヒープ追加確保ゼロ | + +### in-place vs Pure 比較 + +| 方式 | Time | Space | 特徴 | +| ---------------------- | ---- | ----- | ----------------------------------------- | +| **in-place(本実装)** | O(n) | O(1) | 元のノードを再利用。ヒープ確保なし | +| 配列変換+再構築 | O(n) | O(n) | 可読性高いが不要なオブジェクト生成あり | +| 再帰 | O(n) | O(n) | コール スタック消費。n ≤ 300 なら許容範囲 | + +--- + +

Python 実装

+ +```python +from __future__ import annotations + +from typing import Optional, TYPE_CHECKING + +if TYPE_CHECKING: + # pylance / mypy 用の型スタブ(実行時には評価されない) + class ListNode: + val: int + next: Optional[ListNode] + + def __init__( + self, val: int = 0, next: Optional[ListNode] = None + ) -> None: ... + +try: + # LeetCode 実行環境では ListNode が既に定義済み → そのまま利用 + ListNode # type: ignore[used-before-def] +except NameError: + # ローカル実行用の最小フォールバック + class ListNode: # type: ignore[no-redef] + __slots__ = ("val", "next") + + def __init__( + self, val: int = 0, next: Optional[ListNode] = None + ) -> None: + self.val = val + self.next = next + + +class Solution: + """ + LeetCode #83 — Remove Duplicates from Sorted List + + 業務開発版(型安全・pylance 対応)と + 競技プログラミング版(最速・最小)の 2 パターンを提供。 + """ + + # ------------------------------------------------------------------ # + # 業務開発版 ── 型安全・可読性・pylance 対応 # + # ------------------------------------------------------------------ # + def deleteDuplicates( + self, head: Optional[ListNode] + ) -> Optional[ListNode]: + """ + ソート済み連結リストの重複ノードをインプレースで削除する(業務開発版) + + Args: + head: 連結リストの先頭ノード(空リストの場合は None) + + Returns: + 重複を除いたソート済み連結リストの先頭ノード + + Time Complexity: O(n) ─ 各ノードを最大 1 回走査 + Space Complexity: O(1) ─ ポインタ変数のみ、追加メモリなし + """ + # ── ガード節 ──────────────────────────────────────────────────── + # 空リスト or ノードが 1 つ → 重複なし、そのまま返す + if head is None or head.next is None: + return head + + # ── 1 ポインタ走査(インプレース) ──────────────────────────── + current: ListNode = head + + while current.next is not None: + # LOAD_ATTR 削減のため current.next をローカル変数にキャッシュ + nxt: ListNode = current.next + + if current.val == nxt.val: + # 重複検出 → nxt をスキップ(current は移動しない) + # 次のノードも同値の可能性があるため current は据え置き + current.next = nxt.next + else: + # 値が異なる → current を 1 つ前進 + current = nxt + + return head + + # ------------------------------------------------------------------ # + # 競技プログラミング版 ── 最速・型チェック省略 # + # ------------------------------------------------------------------ # + def deleteDuplicates_competitive( + self, head: Optional[ListNode] + ) -> Optional[ListNode]: + """ + 競技プログラミング向け最適化実装 + + - エラーハンドリング省略 + - ローカル変数キャッシュで LOAD_ATTR を削減 + - CPython の属性参照コストを最小化 + + Time Complexity: O(n) + Space Complexity: O(1) + """ + cur = head + while cur and cur.next: + nxt = cur.next + if cur.val == nxt.val: + cur.next = nxt.next # スキップ(cur は移動しない) + else: + cur = nxt # 前進 + return head +``` + +--- + +

CPython 最適化ポイント

+ +### 属性アクセスのキャッシュ + +```python +# ❌ 遅い: 毎回 LOAD_ATTR が 2 回発生 +while current.next is not None: + if current.val == current.next.val: + current.next = current.next.next + +# ✅ 速い: nxt にキャッシュして LOAD_ATTR を削減 +while current.next is not None: + nxt = current.next # ← ここで 1 回だけ LOAD_ATTR + if current.val == nxt.val: + current.next = nxt.next +``` + +| テクニック | 効果 | 本問題への適用 | +| ------------------------ | -------------------------------------------------- | ----------------------- | +| ローカル変数キャッシュ | `LOAD_ATTR` → `LOAD_FAST`(約 2 倍高速) | `nxt = current.next` ✅ | +| `while cur and cur.next` | `None` チェックを CPython の truthiness で短絡評価 | 競技版で適用 ✅ | +| スライス回避 | 不要なリストコピーを避ける | 本問題は不要 — | +| `lru_cache` | 再帰的メモ化 | 本問題は不要 — | +| `bisect` | ソート済み配列への二分探索 | 本問題は不要 — | + +### なぜ配列変換しないか + +```python +# ❌ 配列変換+再構築(O(n) 追加メモリ) +vals = [] +cur = head +while cur: + if not vals or vals[-1] != cur.val: + vals.append(cur.val) + cur = cur.next +# → 新規 ListNode を n 個生成するコストが発生 +``` + +ポインタ付け替えのみなら新規オブジェクト生成ゼロで、GC 負荷も最小になる。 + +--- + +

エッジケースと検証観点

+ +| ケース | 入力 | 期待出力 | 対処 | +| ------------ | ----------------------- | ------------ | ----------------------------------- | +| 空リスト | `head = None` | `None` | ガード節で即時 return | +| ノード 1 つ | `[5]` | `[5]` | `head.next is None` で即時 return | +| 全て同値 | `[3, 3, 3]` | `[3]` | inner while が連続スキップ | +| 全て異なる | `[1, 2, 3]` | `[1, 2, 3]` | 重複検出なし、そのまま return | +| 2 ノード重複 | `[1, 1]` | `[1]` | 1 回スキップして終了 | +| 先頭のみ重複 | `[1, 1, 2, 3]` | `[1, 2, 3]` | Step 1 でスキップ | +| 末尾のみ重複 | `[1, 2, 3, 3]` | `[1, 2, 3]` | 最終ステップでスキップ | +| 最大制約 | n = 300, 全値 −100〜100 | 重複除去済み | O(n) で問題なし | +| 負の値を含む | `[-3, -3, 0, 1, 1]` | `[-3, 0, 1]` | `==` 比較なので値の正負に依存しない | + +--- + +

FAQ

+ +**Q1. `current` を重複スキップ時に前進させない理由は?** + +> ソート済みリストで 3 つ以上同値が連続する場合(例: `[1, 1, 1]`)、1 回スキップしても次も同値の可能性がある。`current` を動かさず再チェックすることで、連続する全重複を正しく除去できる。 + +**Q2. スキップされたノード(旧 `next`)のメモリはどうなる?** + +> Python は参照カウント方式の GC を持つ。`current.next = nxt.next` で `nxt` への参照が消えると、`nxt` の参照カウントが 0 になり即座に解放される(CPython の場合)。 + +**Q3. なぜ再帰で実装しないのか?** + +> 再帰版は可読性が高いが、呼び出しスタックを `O(n)` 消費する。本問題は `n ≤ 300` なので実用上問題ないが、反復版の方がスタックオーバーフローリスクがなく、空間計算量も `O(1)` と優れるため反復を選択した。 + +**Q4. `head.next is None` のガードは本当に必要か?** + +> 厳密にはなくても動作する(`while current.next is not None` が即座にスキップされるため)。しかし「ノードが 1 つ以下なら変更不要」という意図を明示することで可読性と保守性が向上するため、明示的に記述している。 + +**Q5. 競技プログラミング版と業務開発版の実行速度差は?** + +> `n ≤ 300` の小規模入力では測定誤差レベルの差しか生じない。大規模入力(n が数万〜数十万)では `LOAD_ATTR` のキャッシュ効果が現れ始めるが、本問題の制約では本質的な差はない。業務コードでは可読性・型安全性を優先した実装を推奨する。 diff --git a/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html new file mode 100644 index 00000000..ff70aa9b --- /dev/null +++ b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html @@ -0,0 +1,1277 @@ + + + + + + LeetCode #83 - Remove Duplicates from Sorted List + + + + + + + + + + + + + + + + + + + +
+ + + + +
+

+ アルゴリズム概要 +

+ +
+
+
O(n)
+
時間計算量
+
+
+
O(1)
+
空間計算量
+
+
+
+ 0 〜 300 +
+
ノード数制約
+
+
+
+ -100〜100 +
+
値の範囲
+
+
+ +
+

問題の要点

+

+ ソート済み単方向連結リストの先頭ノード + head + を受け取り、 各要素がちょうど 1 回だけ現れるようにリストを変更して返す。
+ ソート済みであるという特性から、重複は必ず隣接して現れる。 これにより 1 + パスの線形走査で解決できる。 +

+
+ +
+
+
入力例 1
+
head = [1, 1, 2]
+
出力: [1, 2]
+
+
+
入力例 2
+
head = [1, 1, 2, 3, 3]
+
出力: [1, 2, 3]
+
+
+ +
+
⚠️ 落とし穴
+
    +
  • + 🔸 重複スキップ後に + current + を進めてはいけない(3連続重複を見逃す) +
  • +
  • + 🔸 head is None と + head.next is None + の両方をガード +
  • +
  • 🔸 新しいノードを作成しない — インプレースでポインタだけ付け替える
  • +
+
+
+ + +
+

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

+
+
+ + +
+

+ 実装コード +

+
+
+ + +
+

+ 処理フローチャート +

+ + +
+
+ 開始 / 終了 +
+
+ 処理ノード +
+
+ 条件分岐 +
+
+ はい / 正常終了 +
+
+ 重複検出 +
+
+ ループバック +
+
+ +
+
+ flowchart TD + Start([" 開始 "]) + Guard["ガード節
head is None OR head.next is None ?"] + GuardTrue["return head
変更なしで即時返却"] + Init["初期化
current = head"] + LoopCheck{"current.next
is not None ?"} + Cache["nxt = current.next
次ノードをキャッシュ"] + DupCheck{"current.val
== nxt.val ?"} + Skip["nxt をスキップ
current.next = nxt.next
※ current は動かさない"] + Advance["current を前進
current = nxt"] + Return["return head
重複除去済みリストを返す"] + End([" 終了 "]) + + Start --> Guard + Guard -- "True
空 or 単一ノード" --> GuardTrue + Guard -- "False
複数ノード存在" --> Init + GuardTrue --> End + Init --> LoopCheck + LoopCheck -- "False
current.next が None
ループ終了" --> Return + LoopCheck -- "True
次ノード存在" --> Cache + Cache --> DupCheck + DupCheck -- "True
重複あり" --> Skip + DupCheck -- "False
重複なし" --> Advance + Skip -- "再チェック
同じ current で
ループ先頭へ戻る" --> LoopCheck + Advance -- "次ノードへ
ループ先頭へ戻る" --> LoopCheck + Return --> End + + style Start fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 + style End fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 + style Guard fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e + style GuardTrue fill:#d1fae5,stroke:#059669,stroke-width:2px,color:#065f46 + style Init fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e + style LoopCheck fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e + style Cache fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b + style DupCheck fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e + style Skip fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#991b1b + style Advance fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b + style Return fill:#d1fae5,stroke:#059669,stroke-width:2.5px,color:#065f46 + + linkStyle 0 stroke:#64748b,stroke-width:2px + linkStyle 1 stroke:#059669,stroke-width:2px + linkStyle 2 stroke:#64748b,stroke-width:2px + linkStyle 3 stroke:#059669,stroke-width:2px + linkStyle 4 stroke:#64748b,stroke-width:2px + linkStyle 5 stroke:#059669,stroke-width:2px + linkStyle 6 stroke:#64748b,stroke-width:2px + linkStyle 7 stroke:#64748b,stroke-width:2px + linkStyle 8 stroke:#dc2626,stroke-width:2px + linkStyle 9 stroke:#64748b,stroke-width:2px + linkStyle 10 stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 + linkStyle 11 stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 + linkStyle 12 stroke:#059669,stroke-width:2px +
+
+ + +
+
+
+ ① ガード節(Guard) +
+

+ リストが空(None)、またはノードが1つ(head.next is None)なら重複は存在しない。head を返して終了(緑の矢印)。 +

+
+
+
+ ② ループ条件チェック +
+

+ current.next is None + になったらループ終了(緑矢印 → return)。
current.next + が存在する間は内部処理を継続(下方向)。 +

+
+
+
+ ③ 重複検出 → Skip(赤矢印) +
+

+ current.val == nxt.val なら + current.next = nxt.next で + nxt を切り離す。current は移動せず、ループ先頭へ戻って再チェック(紫の破線)。 +

+
+
+
+ ④ 値が異なる → Advance(紫破線) +
+

+ current.val != nxt.val なら + current = nxt + で1つ前進。ループ先頭へ戻って次のノードを比較(紫の破線)。 +

+
+
+
+ + +
+

+ 計算量分析 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ 指標 + + 値 + + 理由 +
+ 時間計算量 + + O(n) + + 各ノードを最大 1 回走査。重複スキップ時も + current は移動しないが、next + の参照が前進するため全体では O(n) +
+ 空間計算量 + + O(1) + + スタック変数 current / + nxt のみ。新規ノード生成ゼロ +
+ ヒープ確保 + + 0 回 + + 既存ノードの + next + 付け替えのみ。新オブジェクト生成なし +
+
+ +
+

アプローチ比較

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ アプローチ + + Time + + Space + + 特徴 +
+ ✅ 1ポインタ・インプレース(本実装) + + O(n) + + O(1) + + 最適。ヒープ確保ゼロ +
+ 再帰 + + O(n) + + O(n) + + 可読性高いがコールスタック消費 +
+ 配列変換+再構築 + + O(n) + + O(n) + + 不要なオブジェクト生成多数 +
+
+
+
+ + + + + + + + diff --git a/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Python.md b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Python.md new file mode 100644 index 00000000..166f5c71 --- /dev/null +++ b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Python.md @@ -0,0 +1,191 @@ +# LeetCode #83 - Remove Duplicates from Sorted List (Python) + +--- + +## 1. 問題分析結果 + +### 競技プログラミング視点 + +- **制約分析**: `n ≤ 300` と極小 → アルゴリズムより**ポインタ操作の正確性**が支配的 +- **最速手法**: 1ポインタ線形走査 `O(n)` / 追加メモリなし `O(1)` +- **メモリ最小化**: インプレース `next` 付け替えのみ → 新規オブジェクト生成ゼロ +- **CPython最適化**: 属性アクセス(`obj.attr`)はCPythonでコスト高 → ローカル変数へキャッシュ + +### 業務開発視点 + +- **型安全設計**: `Optional[ListNode]` を厳密に使い、Pylance エラーゼロを確保 +- **エラーハンドリング**: `head is None` / `head.next is None` をガード節で明示 +- **可読性**: ステップごとにコメントを付与し、意図を明示 + +### Python特有分析 + +- **データ構造**: 連結リストのノードは `ListNode` クラス → Python オブジェクト参照で管理 +- **標準ライブラリ**: 本問題では不要(ポインタ操作のみ) +- **CPython最適化**: `current.next` の繰り返しアクセスを `nxt` ローカル変数でキャッシュ → LOAD_ATTR 削減 + +--- + +## 2. アプローチ比較 + +| アプローチ | 時間計算量 | 空間計算量 | Python実装コスト | 可読性 | CPython最適化 | 備考 | +| --------------------------- | ---------- | ---------- | ---------------- | ------ | ------------- | --------------------------- | +| **1ポインタ・インプレース** | O(n) | O(1) | 低 | ★★★ | 適 | ✅ 最適解 | +| 再帰 | O(n) | O(n) | 低 | ★★★ | 不適 | スタック消費・n≤300なら許容 | +| 配列変換+再構築 | O(n) | O(n) | 中 | ★★☆ | 不適 | 不要なオブジェクト生成 | + +--- + +## 3. 採用アルゴリズムと根拠 + +- **選択**: 1ポインタ・インプレース走査 +- **理由**: ソート済みという特性上、重複は**必ず隣接**するため1パスで完結。`O(1)` 追加メモリで最適 +- **Python最適化戦略**: `current.next` の属性アクセスをローカル変数 `nxt` にキャッシュし LOAD_ATTR を削減 +- **トレードオフ**: 競技版は型チェック省略で最速、業務版は Pylance 対応の型安全を優先 + +--- + +## 4. 実装 + +```python +# Runtime 0 ms +# Beats 100.00% +# Memory 19.30 MB +# Beats 91.01% +from typing import Optional + + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val: int = 0, next: Optional['ListNode'] = None) -> None: +# self.val = val +# self.next = next + + +class Solution: + """ + LeetCode #83 - Remove Duplicates from Sorted List + + ソート済み連結リストから重複ノードをインプレースで削除する。 + 業務開発版(型安全・Pylance対応)と + 競技プログラミング版(最速・最小)の2パターンを提供。 + """ + + # ------------------------------------------------------------------ # + # 業務開発版 ── 型安全・可読性・Pylance 対応 # + # ------------------------------------------------------------------ # + def deleteDuplicates(self, head: Optional['ListNode']) -> Optional['ListNode']: + """ + ソート済み連結リストの重複ノードを削除する(業務開発版) + + Args: + head: 連結リストの先頭ノード(空リストの場合は None) + + Returns: + 重複を除いたソート済み連結リストの先頭ノード + + Time Complexity: O(n) ─ 各ノードを最大1回走査 + Space Complexity: O(1) ─ ポインタ変数のみ、追加メモリなし + """ + # ── ガード節 ──────────────────────────────────────────────────── + # 空リスト、またはノードが1つ → 重複なし、そのまま返す + if head is None or head.next is None: + return head + + # ── 1ポインタ走査(インプレース) ───────────────────────────── + current: ListNode = head # type: ignore[name-defined] + + while current.next is not None: + nxt: ListNode = current.next # type: ignore[name-defined] + # ┌──────────────────────────────────────────────┐ + # │ 重複検出: current.val == nxt.val │ + # │ │ + # │ [1] → [1] → [2] │ + # │ ↑ ↑ │ + # │ cur nxt (スキップ対象) │ + # │ │ + # │ [1] ──────────→ [2] ← nxt.next を接続 │ + # └──────────────────────────────────────────────┘ + if current.val == nxt.val: + # 重複 → nxt をスキップ(current は進めない) + # 次のノードも同値の可能性があるため + current.next = nxt.next + else: + # 異なる値 → current を1つ進める + current = nxt + + return head + + # ------------------------------------------------------------------ # + # 競技プログラミング版 ── 最速・型チェック省略 # + # ------------------------------------------------------------------ # + def deleteDuplicates_competitive( + self, head: Optional['ListNode'] + ) -> Optional['ListNode']: + """ + 競技プログラミング向け最適化実装 + + - エラーハンドリング省略 + - ローカル変数キャッシュで LOAD_ATTR を削減 + - CPython の属性参照コストを最小化 + + Time Complexity: O(n) + Space Complexity: O(1) + """ + cur = head + while cur and cur.next: + # cur.next を nxt にキャッシュ → LOAD_ATTR 削減 + nxt = cur.next + if cur.val == nxt.val: + cur.next = nxt.next # スキップ(cur は移動しない) + else: + cur = nxt # 前進 + return head +``` + +--- + +## 5. ポインタ操作の可視化 + +``` +【入力】 head = [1, 1, 2, 3, 3] + +Step 1 cur.val(1) == nxt.val(1) → nxt をスキップ + [1] → [1] → [2] → [3] → [3] → None + ↑ + cur + ↓ cur.next = nxt.next + [1] ──────→ [2] → [3] → [3] → None + ↑ + cur ※ cur は移動しない(次も重複の可能性) + +Step 2 cur.val(1) != nxt.val(2) → cur を前進 + [1] → [2] → [3] → [3] → None + ↑ + cur + +Step 3 cur.val(2) != nxt.val(3) → cur を前進 + [1] → [2] → [3] → [3] → None + ↑ + cur + +Step 4 cur.val(3) == nxt.val(3) → nxt をスキップ + [1] → [2] → [3] → None + ↑ + cur + +Step 5 cur.next is None → ループ終了 + +【出力】 [1, 2, 3] ✅ +``` + +--- + +## 6. 計算量サマリー + +| 指標 | 値 | 説明 | +| --------------- | ------ | ----------------------------------------- | +| **時間計算量** | `O(n)` | 各ノードを最大1回走査 | +| **空間計算量** | `O(1)` | ローカル変数のみ、追加構造なし | +| **安定性** | ✅ | 元の順序・値を保持 | +| **破壊的操作** | ✅ | 元リストをインプレースで変更 | +| **Pylance対応** | ✅ | `Optional[ListNode]` で静的解析エラーなし | diff --git a/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Rust.md b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Rust.md new file mode 100644 index 00000000..d97f7598 --- /dev/null +++ b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Rust.md @@ -0,0 +1,190 @@ +# LeetCode #83 - Remove Duplicates from Sorted List (Rust) + +--- + +## 1. 問題の分析 + +### 競技プログラミング視点 + +- **制約分析**: `n ≤ 300` → アルゴリズムより**所有権モデルとの格闘**が主戦場 +- **最速手法**: 1ポインタ線形走査 `O(n)` / 追加ヒープアロケーションゼロ `O(1)` +- **メモリ最小化**: `Box` の drop を `take()` で制御し、不要ノードを即座に解放 + +### 業務開発視点 + +- **型安全設計**: `Option>` が Rust での連結リスト表現 → `None` = リスト終端が型レベルで保証 +- **エラーハンドリング**: `Option` の `map_or` / `take` で null 相当の安全な操作 +- **所有権設計**: 関数が `head` の所有権を受け取り、変更済みリストの所有権を返す + +### Rust特有の考慮点 + +- `Option>` の二重ラップ → `as_mut()` / `take()` / `.next` の連鎖が肝 +- **借用チェッカーとの戦い**: `current` への `&mut` を保持しつつ `node.next` を書き換える → `while let` ループで解決 +- スタック上の `current: Option<&mut Box>` のみ → ヒープ追加確保ゼロ + +--- + +## 2. アルゴリズムアプローチ比較 + +| アプローチ | 時間計算量 | 空間計算量 | Rust実装コスト | 安全性 | 可読性 | 備考 | +| --------------------------- | ---------- | ---------- | -------------- | ------ | ------ | ------------------------ | +| **1ポインタ・インプレース** | O(n) | O(1) | 中 | 高 | 高 | ✅ 最適解・追加alloc不要 | +| 再帰 | O(n) | O(n) | 低 | 高 | 高 | スタック消費・TCO非保証 | +| Vec収集+再構築 | O(n) | O(n) | 低 | 高 | 中 | 不要なヒープ確保 | + +--- + +## 3. 選択したアルゴリズムと理由 + +- **選択**: 1ポインタ・インプレース走査 +- **理由**: + - ソート済みリストの隣接重複という特性で1パス完結 + - `Box` の所有権移動を `take()` で明示的に制御 → 解放タイミングが明確 + - 再帰は末尾呼び出し最適化が Rust でコンパイラ保証されないため回避 +- **Rust固有の最適化ポイント**: + - `take()` で `next` の所有権を一時取り出し → 借用チェッカーを満足させる慣用パターン + - `as_mut()` で `Option>` を `Option<&mut Box>` に変換 → ゼロコスト + - スタック変数 `current` のみ → キャッシュフレンドリー + +--- + +## 4. 実装コード + +```rust +// Runtime 0 ms +// Beats 100.00% +// Memory 2.13 MB +// Beats 68.10% +// Definition for singly-linked list. +// #[derive(PartialEq, Eq, Clone, Debug)] +// pub struct ListNode { +// pub val: i32, +// pub next: Option> +// } +// +// impl ListNode { +// #[inline] +// fn new(val: i32) -> Self { +// ListNode { +// next: None, +// val +// } +// } +// } + +impl Solution { + /// ソート済み連結リストから重複ノードをインプレースで削除する + /// + /// # Algorithm + /// `current` ポインタを先頭から走査し、 + /// `current.val == current.next.val` の間は `next` を `take()` でスキップ。 + /// 値が異なった時点で `current` を1つ進める(1ポインタ・インプレース)。 + /// + /// # Arguments + /// * `head` - 連結リストの所有権(空リストの場合は `None`) + /// + /// # Returns + /// 重複を除去したソート済み連結リストの所有権 + /// + /// # Complexity + /// - Time: O(n) — 各ノードを最大1回走査 + /// - Space: O(1) — スタック変数のみ、追加ヒープ確保なし + pub fn delete_duplicates(head: Option>) -> Option> { + // head の所有権を受け取り、変更後に返す + let mut head = head; + + // ── ガード節 ──────────────────────────────────────────────────── + // 空リスト or ノード1つ → 重複なし、所有権をそのまま返す + if head.is_none() || head.as_ref().unwrap().next.is_none() { + return head; + } + + // ── 1ポインタ走査(インプレース) ───────────────────────────── + // + // current: Option<&mut Box> + // - as_mut() で head の &mut 参照を取得 + // - ループ内で node.next.as_mut() により1つずつ前進 + // + // 【所有権の流れ】 + // head(所有) ──as_mut()──> current(&mut) + // current は head を所有したまま参照だけを持ち歩く + // + let mut current = head.as_mut(); + + while let Some(node) = current { + // ┌──────────────────────────────────────────────────────┐ + // │ 内側ループ: 同じ値が連続する限り next をスキップ │ + // │ │ + // │ [1] → [1] → [2] │ + // │ ↑ ↑ │ + // │ node next (take で所有権を取り出しドロップ) │ + // │ │ + // │ take() の動作: │ + // │ node.next の所有権を `skipped` へ移動 │ + // │ node.next は None になる │ + // │ skipped.next を node.next へ接続 │ + // │ skipped は スコープを抜けて自動 drop │ + // └──────────────────────────────────────────────────────┘ + while node.next.as_ref().map_or(false, |nxt| nxt.val == node.val) { + // next の所有権を取り出す(node.next は一時的に None) + let skipped = node.next.take().unwrap(); // Box + // スキップされたノードの next を現在ノードの next へ接続 + node.next = skipped.next; + // skipped はここで drop → ヒープ解放 + } + + // 値が異なる → current を1つ前進 + current = node.next.as_mut(); + } + + head // 変更済みリストの所有権を返す + } +} +``` + +--- + +## 5. 所有権フローの可視化 + +``` +【入力】 head = Some([1] → [1] → [2] → [3] → [3] → None) + +┌─ head (所有) ─────────────────────────────────────────────┐ +│ as_mut() で &mut を取り出し current へ │ +└────────────────────────────────────────────────────────────┘ + +Step 1 node.val(1) == next.val(1) → take() でスキップ + before: [1] → [1] → [2] → [3] → [3] → None + take(): skipped = Box([1] → [2] → ...) + after: [1] ──────→ [2] → [3] → [3] → None + drop: skipped (旧2番目ノード) を即時解放 ✅ + +Step 2 node.val(1) != next.val(2) → current を前進 + current → [2] + +Step 3 node.val(2) != next.val(3) → current を前進 + current → [3] + +Step 4 node.val(3) == next.val(3) → take() でスキップ + before: [3] → [3] → None + take(): skipped = Box([3] → None) + after: [3] → None + drop: skipped を即時解放 ✅ + +Step 5 node.next is None → while let を抜ける + +【出力】 Some([1] → [2] → [3] → None) ✅ +``` + +--- + +## 6. 計算量サマリー + +| 指標 | 値 | 説明 | +| ------------------ | ----------- | ---------------------------------- | +| **時間計算量** | `O(n)` | 各ノードを最大1回走査 | +| **空間計算量** | `O(1)` | スタック変数 `current` のみ | +| **ヒープ確保** | `0` 回 | 既存ノードの `next` 付け替えのみ | +| **安全性** | `safe Rust` | `unsafe` ブロックなし | +| **重複ノード解放** | 即時 | `take()` スコープ末尾で自動 `drop` | +| **clippy 適合** | ✅ | `#![deny(clippy::all)]` 相当 | diff --git a/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Typescript.md b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Typescript.md new file mode 100644 index 00000000..e335bdd7 --- /dev/null +++ b/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/Remove_Duplicates_from_Sorted_List_Typescript.md @@ -0,0 +1,163 @@ +# LeetCode #83 - Remove Duplicates from Sorted List + +--- + +## 1. 問題の分析 + +### 競技プログラミング視点での分析 + +- ソート済みリストなので、**重複は必ず隣接**する → 1パスで解決可能 +- ポインタ操作のみ → 追加メモリ不要 `O(1)` space +- `n ≤ 300` と小さいため、計算量よりも**ポインタの正確な操作**が肝 + +### 業務開発視点での分析 + +- `ListNode | null` の Union型を正確に扱う null安全性が重要 +- 破壊的操作(`next`の付け替え)のため、**副作用を局所化**した明確な実装が必要 +- 型ガードで `current.next` の null チェックを明示 + +### TypeScript特有の考慮点 + +- `ListNode | null` → `!= null` での絞り込みで型ガード +- `while` ループ内での型推論を活用し、余分なキャストを排除 +- `readonly` は付けられない(破壊的操作必須)のでその代わりに関数スコープで副作用を限定 + +--- + +## 2. アルゴリズムアプローチ比較 + +| アプローチ | 時間計算量 | 空間計算量 | TS実装コスト | 型安全性 | 可読性 | 備考 | +| ------------------------- | ---------- | ---------- | ------------ | -------- | ------ | ---------------------------- | +| **インプレース1ポインタ** | O(n) | O(1) | 低 | 高 | 高 | ✅ 最適解 | +| 再帰 | O(n) | O(n) | 低 | 高 | 高 | スタックオーバーフローリスク | +| 配列変換+再構築 | O(n) | O(n) | 中 | 高 | 中 | 不要なメモリ確保 | + +--- + +## 3. 選択したアルゴリズムと理由 + +- **選択**: インプレース1ポインタ走査 +- **理由**: + - ソート済みリストの特性(隣接する重複)を最大限に活かし、1パスで完結 + - `O(1)` 追加メモリ、`O(n)` 時間の最適バランス + - 再帰は `n≤300` では問題ないが、スタック消費の観点で反復が優位 +- **TypeScript最適化ポイント**: + - `current` の型が `while` の条件式で `ListNode` に自動的に絞り込まれる型推論を活用 + - `current.next !== null` チェック後、型が自動的に `ListNode` へ narrowing + +--- + +## 4. 実装コード + +```typescript +// Runtime 0 ms +// Beats 100.00% +// Memory 58.86 MB +// Beats 26.83% +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +/** + * ソート済み連結リストから重複ノードを削除する + * + * アルゴリズム: + * current ポインタを先頭から走査し、 + * current.val === current.next.val の間は next を読み飛ばす。 + * 値が異なった時点で current を進める(1ポインタ・インプレース) + * + * @param head - 連結リストの先頭ノード (null の場合は空リスト) + * @returns 重複を除去したソート済み連結リストの先頭ノード + * @complexity Time: O(n), Space: O(1) + */ +function deleteDuplicates(head: ListNode | null): ListNode | null { + // ── 入力ガード ────────────────────────────────────────── + // 空リスト or ノードが1つ → 重複なし、そのまま返す + if (head === null || head.next === null) { + return head; + } + + // ── 1ポインタ走査(インプレース) ──────────────────────── + // TypeScriptの型narrowing: + // while条件で current != null が保証されるため + // ループ内で current は ListNode 型として扱われる + let current: ListNode = head; + + while (current.next !== null) { + // current.next は null でないことが確定(型: ListNode) + if (current.val === current.next.val) { + // ┌─────────────────────────────────────────┐ + // │ 重複検出: current.next をスキップ │ + // │ │ + // │ [1] → [1] → [2] │ + // │ ↑ ↑ │ + // │ current next(スキップ) │ + // │ │ + // │ [1] ──────→ [2] ← next.next を接続 │ + // └─────────────────────────────────────────┘ + current.next = current.next.next; + // current は進めない(次も重複の可能性があるため) + } else { + // 値が異なる → current を1つ進める + current = current.next; + } + } + + return head; +} +``` + +--- + +## ポインタ操作の可視化 + +``` +【初期状態】 head = [1, 1, 2, 3, 3] + +Step 1: current.val(1) === current.next.val(1) → next をスキップ + [1] → [1] → [2] → [3] → [3] → null + ↑ + current + ↓ current.next = current.next.next + [1] ──────→ [2] → [3] → [3] → null + ↑ + current + +Step 2: current.val(1) !== current.next.val(2) → current を進める + [1] → [2] → [3] → [3] → null + ↑ + current + +Step 3: current.val(2) !== current.next.val(3) → current を進める + [1] → [2] → [3] → [3] → null + ↑ + current + +Step 4: current.val(3) === current.next.val(3) → next をスキップ + [1] → [2] → [3] → null + ↑ + current + +Step 5: current.next === null → ループ終了 + +【出力】 [1, 2, 3] ✅ +``` + +--- + +## 計算量サマリー + +| 指標 | 値 | 説明 | +| -------------- | ------ | ----------------------------------- | +| **時間計算量** | `O(n)` | 各ノードを最大1回走査 | +| **空間計算量** | `O(1)` | ポインタ変数1つのみ、追加メモリなし | +| **安定性** | ✅ | 元の順序・値を保持 | +| **破壊的操作** | ✅ | 元リストをインプレースで変更 | diff --git a/public/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html b/public/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html new file mode 100644 index 00000000..4ab5782a --- /dev/null +++ b/public/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html @@ -0,0 +1,1277 @@ + + + + + + LeetCode #83 - Remove Duplicates from Sorted List + + + + + + + + + + + + + + + + + + + +
+ + + + +
+

+ アルゴリズム概要 +

+ +
+
+
O(n)
+
時間計算量
+
+
+
O(1)
+
空間計算量
+
+
+
+ 0 〜 300 +
+
ノード数制約
+
+
+
+ -100〜100 +
+
値の範囲
+
+
+ +
+

問題の要点

+

+ ソート済み単方向連結リストの先頭ノード + head + を受け取り、 各要素がちょうど 1 回だけ現れるようにリストを変更して返す。
+ ソート済みであるという特性から、重複は必ず隣接して現れる。 これにより 1 + パスの線形走査で解決できる。 +

+
+ +
+
+
入力例 1
+
head = [1, 1, 2]
+
出力: [1, 2]
+
+
+
入力例 2
+
head = [1, 1, 2, 3, 3]
+
出力: [1, 2, 3]
+
+
+ +
+
⚠️ 落とし穴
+
    +
  • + 🔸 重複スキップ後に + current + を進めてはいけない(3連続重複を見逃す) +
  • +
  • + 🔸 head is None と + head.next is None + の両方をガード +
  • +
  • 🔸 新しいノードを作成しない — インプレースでポインタだけ付け替える
  • +
+
+
+ + +
+

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

+
+
+ + +
+

+ 実装コード +

+
+
+ + +
+

+ 処理フローチャート +

+ + +
+
+ 開始 / 終了 +
+
+ 処理ノード +
+
+ 条件分岐 +
+
+ はい / 正常終了 +
+
+ 重複検出 +
+
+ ループバック +
+
+ +
+
+ flowchart TD + Start([" 開始 "]) + Guard["ガード節
head is None OR head.next is None ?"] + GuardTrue["return head
変更なしで即時返却"] + Init["初期化
current = head"] + LoopCheck{"current.next
is not None ?"} + Cache["nxt = current.next
次ノードをキャッシュ"] + DupCheck{"current.val
== nxt.val ?"} + Skip["nxt をスキップ
current.next = nxt.next
※ current は動かさない"] + Advance["current を前進
current = nxt"] + Return["return head
重複除去済みリストを返す"] + End([" 終了 "]) + + Start --> Guard + Guard -- "True
空 or 単一ノード" --> GuardTrue + Guard -- "False
複数ノード存在" --> Init + GuardTrue --> End + Init --> LoopCheck + LoopCheck -- "False
current.next が None
ループ終了" --> Return + LoopCheck -- "True
次ノード存在" --> Cache + Cache --> DupCheck + DupCheck -- "True
重複あり" --> Skip + DupCheck -- "False
重複なし" --> Advance + Skip -- "再チェック
同じ current で
ループ先頭へ戻る" --> LoopCheck + Advance -- "次ノードへ
ループ先頭へ戻る" --> LoopCheck + Return --> End + + style Start fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 + style End fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 + style Guard fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e + style GuardTrue fill:#d1fae5,stroke:#059669,stroke-width:2px,color:#065f46 + style Init fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e + style LoopCheck fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e + style Cache fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b + style DupCheck fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e + style Skip fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#991b1b + style Advance fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b + style Return fill:#d1fae5,stroke:#059669,stroke-width:2.5px,color:#065f46 + + linkStyle 0 stroke:#64748b,stroke-width:2px + linkStyle 1 stroke:#059669,stroke-width:2px + linkStyle 2 stroke:#64748b,stroke-width:2px + linkStyle 3 stroke:#059669,stroke-width:2px + linkStyle 4 stroke:#64748b,stroke-width:2px + linkStyle 5 stroke:#059669,stroke-width:2px + linkStyle 6 stroke:#64748b,stroke-width:2px + linkStyle 7 stroke:#64748b,stroke-width:2px + linkStyle 8 stroke:#dc2626,stroke-width:2px + linkStyle 9 stroke:#64748b,stroke-width:2px + linkStyle 10 stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 + linkStyle 11 stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 + linkStyle 12 stroke:#059669,stroke-width:2px +
+
+ + +
+
+
+ ① ガード節(Guard) +
+

+ リストが空(None)、またはノードが1つ(head.next is None)なら重複は存在しない。head を返して終了(緑の矢印)。 +

+
+
+
+ ② ループ条件チェック +
+

+ current.next is None + になったらループ終了(緑矢印 → return)。
current.next + が存在する間は内部処理を継続(下方向)。 +

+
+
+
+ ③ 重複検出 → Skip(赤矢印) +
+

+ current.val == nxt.val なら + current.next = nxt.next で + nxt を切り離す。current は移動せず、ループ先頭へ戻って再チェック(紫の破線)。 +

+
+
+
+ ④ 値が異なる → Advance(紫破線) +
+

+ current.val != nxt.val なら + current = nxt + で1つ前進。ループ先頭へ戻って次のノードを比較(紫の破線)。 +

+
+
+
+ + +
+

+ 計算量分析 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ 指標 + + 値 + + 理由 +
+ 時間計算量 + + O(n) + + 各ノードを最大 1 回走査。重複スキップ時も + current は移動しないが、next + の参照が前進するため全体では O(n) +
+ 空間計算量 + + O(1) + + スタック変数 current / + nxt のみ。新規ノード生成ゼロ +
+ ヒープ確保 + + 0 回 + + 既存ノードの + next + 付け替えのみ。新オブジェクト生成なし +
+
+ +
+

アプローチ比較

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ アプローチ + + Time + + Space + + 特徴 +
+ ✅ 1ポインタ・インプレース(本実装) + + O(n) + + O(1) + + 最適。ヒープ確保ゼロ +
+ 再帰 + + O(n) + + O(n) + + 可読性高いがコールスタック消費 +
+ 配列変換+再構築 + + O(n) + + O(n) + + 不要なオブジェクト生成多数 +
+
+
+
+ + + + + + + + diff --git a/public/index.html b/public/index.html index dcc5340e..464fb782 100644 --- a/public/index.html +++ b/public/index.html @@ -416,7 +416,7 @@

🧪 Algorithm Study Index

-

163 interactive lessons across 6 domains

+

164 interactive lessons across 6 domains

@@ -431,9 +431,9 @@

- + @@ -465,6 +465,7 @@

  • 🧩Insert Interval Algorithm AnalysisAlgorithm/Other/leetcode/57. Insert Interval/Claude/README.html
  • 🧩Jump Game Algorithm AnalysisAlgorithm/greedy algorithm/leetcode/55. Jump Game/Claude/README.html
  • 🧩Jump Game II アルゴリズム解析Algorithm/greedy algorithm/leetcode/45. Jump Game II/Claude/README.html
  • +
  • 🧩LeetCode #83 - Remove Duplicates from Sorted ListAlgorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html
  • 🧩LeetCode 5: Longest Palindromic Substring - 中心展開法Algorithm/ExpandAroundCenter/leetcode/5. Longest Palindromic Substring/Claude/README.html
  • 🧩LeetCode 66: Plus One - 右から左への繰り上がり処理Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/README_react.html
  • 🧩LeetCode 67: Add Binary - 二進数加算Algorithm/TwoPointers/leetcode/67. Add Binary/Claude/README_react.html
  • @@ -635,6 +636,7 @@

  • 🧩Insert Interval Algorithm AnalysisAlgorithm/Other/leetcode/57. Insert Interval/Claude/README.html
  • 🧩Jump Game Algorithm AnalysisAlgorithm/greedy algorithm/leetcode/55. Jump Game/Claude/README.html
  • 🧩Jump Game II アルゴリズム解析Algorithm/greedy algorithm/leetcode/45. Jump Game II/Claude/README.html
  • +
  • 🧩LeetCode #83 - Remove Duplicates from Sorted ListAlgorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html
  • 🧩LeetCode 5: Longest Palindromic Substring - 中心展開法Algorithm/ExpandAroundCenter/leetcode/5. Longest Palindromic Substring/Claude/README.html
  • 🧩LeetCode 66: Plus One - 右から左への繰り上がり処理Algorithm/Other/leetcode/66. Plus One/Claude Sonnet 4.5/README_react.html
  • 🧩LeetCode 67: Add Binary - 二進数加算Algorithm/TwoPointers/leetcode/67. Add Binary/Claude/README_react.html
  • @@ -809,7 +811,7 @@

    🧪 - Generated on 2026-03-10 + Generated on 2026-03-11
    - + + @@ -344,58 +344,42 @@

    問題の要点

    - flowchart TD - Start([" 開始 "]) - Guard["ガード節
    head is None OR head.next is None ?"] - GuardTrue["return head
    変更なしで即時返却"] - Init["初期化
    current = head"] - LoopCheck{"current.next
    is not None ?"} - Cache["nxt = current.next
    次ノードをキャッシュ"] - DupCheck{"current.val
    == nxt.val ?"} - Skip["nxt をスキップ
    current.next = nxt.next
    ※ current は動かさない"] - Advance["current を前進
    current = nxt"] - Return["return head
    重複除去済みリストを返す"] - End([" 終了 "]) - - Start --> Guard - Guard -- "True
    空 or 単一ノード" --> GuardTrue - Guard -- "False
    複数ノード存在" --> Init - GuardTrue --> End - Init --> LoopCheck - LoopCheck -- "False
    current.next が None
    ループ終了" --> Return - LoopCheck -- "True
    次ノード存在" --> Cache - Cache --> DupCheck - DupCheck -- "True
    重複あり" --> Skip - DupCheck -- "False
    重複なし" --> Advance - Skip -- "再チェック
    同じ current で
    ループ先頭へ戻る" --> LoopCheck - Advance -- "次ノードへ
    ループ先頭へ戻る" --> LoopCheck - Return --> End - - style Start fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 - style End fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 - style Guard fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e - style GuardTrue fill:#d1fae5,stroke:#059669,stroke-width:2px,color:#065f46 - style Init fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e - style LoopCheck fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e - style Cache fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b - style DupCheck fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e - style Skip fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#991b1b - style Advance fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b - style Return fill:#d1fae5,stroke:#059669,stroke-width:2.5px,color:#065f46 - - linkStyle 0 stroke:#64748b,stroke-width:2px - linkStyle 1 stroke:#059669,stroke-width:2px - linkStyle 2 stroke:#64748b,stroke-width:2px - linkStyle 3 stroke:#059669,stroke-width:2px - linkStyle 4 stroke:#64748b,stroke-width:2px - linkStyle 5 stroke:#059669,stroke-width:2px - linkStyle 6 stroke:#64748b,stroke-width:2px - linkStyle 7 stroke:#64748b,stroke-width:2px - linkStyle 8 stroke:#dc2626,stroke-width:2px - linkStyle 9 stroke:#64748b,stroke-width:2px - linkStyle 10 stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 - linkStyle 11 stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 - linkStyle 12 stroke:#059669,stroke-width:2px + flowchart TD Start([" 開始 "]) Guard["ガード節
    head is None OR + head.next is None ?"] GuardTrue["return head
    変更なしで即時返却"] + Init["初期化
    current = head"] LoopCheck{"current.next
    is not None + ?"} Cache["nxt = current.next
    次ノードをキャッシュ"] + DupCheck{"current.val
    == nxt.val ?"} Skip["nxt をスキップ
    current.next + = nxt.next
    ※ current は動かさない"] Advance["current を前進
    current + = nxt"] Return["return head
    重複除去済みリストを返す"] End([" 終了 "]) + Start --> Guard Guard -- "True
    空 or 単一ノード" --> GuardTrue Guard -- + "False
    複数ノード存在" --> Init GuardTrue --> End Init --> LoopCheck + LoopCheck -- "False
    current.next が None
    ループ終了" --> Return + LoopCheck -- "True
    次ノード存在" --> Cache Cache --> DupCheck DupCheck + -- "True
    重複あり" --> Skip DupCheck -- "False
    重複なし" --> + Advance Skip -- "再チェック
    同じ current で
    ループ先頭へ戻る" --> + LoopCheck Advance -- "次ノードへ
    ループ先頭へ戻る" --> LoopCheck Return + --> End style Start + fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 style End + fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 style Guard + fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e style GuardTrue + fill:#d1fae5,stroke:#059669,stroke-width:2px,color:#065f46 style Init + fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e style LoopCheck + fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e style Cache + fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b style DupCheck + fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e style Skip + fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#991b1b style Advance + fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b style Return + fill:#d1fae5,stroke:#059669,stroke-width:2.5px,color:#065f46 linkStyle 0 + stroke:#64748b,stroke-width:2px linkStyle 1 stroke:#059669,stroke-width:2px + linkStyle 2 stroke:#64748b,stroke-width:2px linkStyle 3 + stroke:#059669,stroke-width:2px linkStyle 4 stroke:#64748b,stroke-width:2px + linkStyle 5 stroke:#059669,stroke-width:2px linkStyle 6 + stroke:#64748b,stroke-width:2px linkStyle 7 stroke:#64748b,stroke-width:2px + linkStyle 8 stroke:#dc2626,stroke-width:2px linkStyle 9 + stroke:#64748b,stroke-width:2px linkStyle 10 + stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 linkStyle 11 + stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 linkStyle 12 + stroke:#059669,stroke-width:2px
    @@ -728,9 +712,7 @@

    アプローチ比較 !n.skip).length; - const allNodes = nodes; - const W = Math.max(520, allNodes.length * (BOX + GAP + ARR)); + const W = Math.max(520, nodes.length * (BOX + GAP + ARR)); const H = 120; // compute x positions for all nodes (including skipped) @@ -745,6 +727,11 @@

    アプローチ比較 !n.skip) + .map((n) => n.val) + .join(' → ')} → None`} > {allNodes.map((node, i) => { if (node.skip) { @@ -937,6 +924,7 @@

    return null; } - ReactDOM.render(, document.getElementById('step-root')); + const root = ReactDOM.createRoot(document.getElementById('step-root')); + root.render();

    Immediate Food Delivery II

    - グループ内最小値抽出 + 条件集計 による O(N) 実装 + グループ内最小値抽出 + 条件集計 による O(N log N) 実装

    主要ポイント

      -
    • 時間計算量: O(N) - 全行を1回走査
    • +
    • 時間計算量: O(N log N) - グループ内ソートが必要
    • 空間計算量: O(顧客数) - 最初の注文のみ保持
    • 最適化: ウィンドウ関数を使用して1パスで処理
    diff --git a/public/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html b/public/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html index df97d2b1..cb4fc6fb 100644 --- a/public/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html +++ b/public/Algorithm/Other/leetcode/83. Remove Duplicates from Sorted List/Claude 4.6 extended/README_React.html @@ -4,8 +4,8 @@ LeetCode #83 - Remove Duplicates from Sorted List - - + + @@ -344,42 +344,58 @@

    問題の要点

    - flowchart TD Start([" 開始 "]) Guard["ガード節
    head is None OR - head.next is None ?"] GuardTrue["return head
    変更なしで即時返却"] - Init["初期化
    current = head"] LoopCheck{"current.next
    is not None - ?"} Cache["nxt = current.next
    次ノードをキャッシュ"] - DupCheck{"current.val
    == nxt.val ?"} Skip["nxt をスキップ
    current.next - = nxt.next
    ※ current は動かさない"] Advance["current を前進
    current - = nxt"] Return["return head
    重複除去済みリストを返す"] End([" 終了 "]) - Start --> Guard Guard -- "True
    空 or 単一ノード" --> GuardTrue Guard -- - "False
    複数ノード存在" --> Init GuardTrue --> End Init --> LoopCheck - LoopCheck -- "False
    current.next が None
    ループ終了" --> Return - LoopCheck -- "True
    次ノード存在" --> Cache Cache --> DupCheck DupCheck - -- "True
    重複あり" --> Skip DupCheck -- "False
    重複なし" --> - Advance Skip -- "再チェック
    同じ current で
    ループ先頭へ戻る" --> - LoopCheck Advance -- "次ノードへ
    ループ先頭へ戻る" --> LoopCheck Return - --> End style Start - fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 style End - fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 style Guard - fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e style GuardTrue - fill:#d1fae5,stroke:#059669,stroke-width:2px,color:#065f46 style Init - fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e style LoopCheck - fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e style Cache - fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b style DupCheck - fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e style Skip - fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#991b1b style Advance - fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b style Return - fill:#d1fae5,stroke:#059669,stroke-width:2.5px,color:#065f46 linkStyle 0 - stroke:#64748b,stroke-width:2px linkStyle 1 stroke:#059669,stroke-width:2px - linkStyle 2 stroke:#64748b,stroke-width:2px linkStyle 3 - stroke:#059669,stroke-width:2px linkStyle 4 stroke:#64748b,stroke-width:2px - linkStyle 5 stroke:#059669,stroke-width:2px linkStyle 6 - stroke:#64748b,stroke-width:2px linkStyle 7 stroke:#64748b,stroke-width:2px - linkStyle 8 stroke:#dc2626,stroke-width:2px linkStyle 9 - stroke:#64748b,stroke-width:2px linkStyle 10 - stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 linkStyle 11 - stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 linkStyle 12 - stroke:#059669,stroke-width:2px + flowchart TD + Start([" 開始 "]) + Guard["ガード節
    head is None OR head.next is None ?"] + GuardTrue["return head
    変更なしで即時返却"] + Init["初期化
    current = head"] + LoopCheck{"current.next
    is not None ?"} + Cache["nxt = current.next
    次ノードをキャッシュ"] + DupCheck{"current.val
    == nxt.val ?"} + Skip["nxt をスキップ
    current.next = nxt.next
    ※ current は動かさない"] + Advance["current を前進
    current = nxt"] + Return["return head
    重複除去済みリストを返す"] + End([" 終了 "]) + + Start --> Guard + Guard -- "True
    空 or 単一ノード" --> GuardTrue + Guard -- "False
    複数ノード存在" --> Init + GuardTrue --> End + Init --> LoopCheck + LoopCheck -- "False
    current.next が None
    ループ終了" --> Return + LoopCheck -- "True
    次ノード存在" --> Cache + Cache --> DupCheck + DupCheck -- "True
    重複あり" --> Skip + DupCheck -- "False
    重複なし" --> Advance + Skip -- "再チェック
    同じ current で
    ループ先頭へ戻る" --> LoopCheck + Advance -- "次ノードへ
    ループ先頭へ戻る" --> LoopCheck + Return --> End + + style Start fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 + style End fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#065f46 + style Guard fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e + style GuardTrue fill:#d1fae5,stroke:#059669,stroke-width:2px,color:#065f46 + style Init fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0c4a6e + style LoopCheck fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e + style Cache fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b + style DupCheck fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#92400e + style Skip fill:#fee2e2,stroke:#dc2626,stroke-width:2px,color:#991b1b + style Advance fill:#f1f5f9,stroke:#64748b,stroke-width:2px,color:#1e293b + style Return fill:#d1fae5,stroke:#059669,stroke-width:2.5px,color:#065f46 + + linkStyle 0 stroke:#64748b,stroke-width:2px + linkStyle 1 stroke:#059669,stroke-width:2px + linkStyle 2 stroke:#64748b,stroke-width:2px + linkStyle 3 stroke:#059669,stroke-width:2px + linkStyle 4 stroke:#64748b,stroke-width:2px + linkStyle 5 stroke:#059669,stroke-width:2px + linkStyle 6 stroke:#64748b,stroke-width:2px + linkStyle 7 stroke:#64748b,stroke-width:2px + linkStyle 8 stroke:#dc2626,stroke-width:2px + linkStyle 9 stroke:#64748b,stroke-width:2px + linkStyle 10 stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 + linkStyle 11 stroke:#a855f7,stroke-width:2px,stroke-dasharray:6 4 + linkStyle 12 stroke:#059669,stroke-width:2px
    @@ -712,7 +728,8 @@

    アプローチ比較アプローチ比較 !n.skip) - .map((n) => n.val) - .join(' → ')} → None`} > {allNodes.map((node, i) => { if (node.skip) { diff --git a/public/SQL/Leetcode/Intermediate Join/1164. Product Price at a Given Date/Claude Sonnet 4.5 Extended/Product_Price_at_a_Given_Date.html b/public/SQL/Leetcode/Intermediate Join/1164. Product Price at a Given Date/Claude Sonnet 4.5 Extended/Product_Price_at_a_Given_Date.html index e0eec1d5..617dc8ff 100644 --- a/public/SQL/Leetcode/Intermediate Join/1164. Product Price at a Given Date/Claude Sonnet 4.5 Extended/Product_Price_at_a_Given_Date.html +++ b/public/SQL/Leetcode/Intermediate Join/1164. Product Price at a Given Date/Claude Sonnet 4.5 Extended/Product_Price_at_a_Given_Date.html @@ -6,10 +6,10 @@ Product Prices - 価格履歴管理 | Pandas解説 - + @@ -337,7 +337,7 @@

    主要ポイント

    return null; } - ReactDOM.render(, document.getElementById('step-root')); + const root = ReactDOM.createRoot(document.getElementById('step-root')); + root.render();

    Immediate Food Delivery II

    - グループ内最小値抽出 + 条件集計 による O(N) 実装 + グループ内最小値抽出 + 条件集計 による O(N log N) 実装

    + - - - + + + - - - + + + - - + + - - + + + - - - + + + - - - + + + - - + + - - - + + + - - + + + + - - - + + + diff --git a/public/Concurrency/1115. Print FooBar Alternately/Claude Sonnet 4.5/README_react.html b/public/Concurrency/1115. Print FooBar Alternately/Claude Sonnet 4.5/README_react.html index e9b43e31..6ef6f0ca 100644 --- a/public/Concurrency/1115. Print FooBar Alternately/Claude Sonnet 4.5/README_react.html +++ b/public/Concurrency/1115. Print FooBar Alternately/Claude Sonnet 4.5/README_react.html @@ -12,19 +12,30 @@ href="/vendor/prismjs/themes/prism-tomorrow.css" rel="stylesheet" /> + + - + - + - + ); + + - - - + + + diff --git a/public/Concurrency/1117. Building H2O/Claude Sonnet 4.5/README_react.html b/public/Concurrency/1117. Building H2O/Claude Sonnet 4.5/README_react.html index 04a8fb28..a6508b51 100644 --- a/public/Concurrency/1117. Building H2O/Claude Sonnet 4.5/README_react.html +++ b/public/Concurrency/1117. Building H2O/Claude Sonnet 4.5/README_react.html @@ -828,11 +828,22 @@

    最適化の比較

    + + - - - + + + + + - - - + + + diff --git a/public/Concurrency/1226. The Dining Philosophers/Claude Sonnet 4.5/README_react.html b/public/Concurrency/1226. The Dining Philosophers/Claude Sonnet 4.5/README_react.html index d44ea771..dfa0e70f 100644 --- a/public/Concurrency/1226. The Dining Philosophers/Claude Sonnet 4.5/README_react.html +++ b/public/Concurrency/1226. The Dining Philosophers/Claude Sonnet 4.5/README_react.html @@ -1034,11 +1034,22 @@

    代替手法との比

    + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - + + + - - + + +
    @@ -860,7 +868,7 @@

    完全な処理フロー

    setTimeout(() => { const newNode = animationController.createNode('15'); - container.insertBefore(newNode, nodes[1]); + container.insertBefore(newNode, container.children[1]); status.textContent = 'erase_at(2)を実行すると...'; }, 4000); } diff --git a/public/DataStructures/Map/leetcode/claude/README_react.html b/public/DataStructures/Map/leetcode/claude/README_react.html index f918b01e..13e5e6fd 100644 --- a/public/DataStructures/Map/leetcode/claude/README_react.html +++ b/public/DataStructures/Map/leetcode/claude/README_react.html @@ -833,11 +833,22 @@

    Two Sum

    + + - - - + + + - + - - + + - - + + - - - - - + + + + + - - - - - + + + + + - - + + diff --git a/public/DataStructures/Stacks/leetcode/85. Maximal Rectangle/GPT/README.html b/public/DataStructures/Stacks/leetcode/85. Maximal Rectangle/GPT/README.html index c8d908f5..1957f6c1 100644 --- a/public/DataStructures/Stacks/leetcode/85. Maximal Rectangle/GPT/README.html +++ b/public/DataStructures/Stacks/leetcode/85. Maximal Rectangle/GPT/README.html @@ -1057,13 +1057,24 @@

    + + - - - - + + + + - - + + - - - - + + + + - - + + - - + + - - - - + + + + - - - + + + - + アルゴリズム比較 + + - - - + + + - - - + + + + @@ -936,9 +944,9 @@

    計算量

    - - - + + + + - - - + + + diff --git a/public/JavaScript/2619. Array Prototype Last/Claude Code Sonnet 4.5/README_react.html b/public/JavaScript/2619. Array Prototype Last/Claude Code Sonnet 4.5/README_react.html index 85d9beb3..fd7a80ef 100644 --- a/public/JavaScript/2619. Array Prototype Last/Claude Code Sonnet 4.5/README_react.html +++ b/public/JavaScript/2619. Array Prototype Last/Claude Code Sonnet 4.5/README_react.html @@ -628,11 +628,21 @@

    最適化ポイント

    + - - - + + + - - - + + + + - - - + + + + - - - + + + - + - + - + diff --git a/public/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README_react.html b/public/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README_react.html index 96d69a9d..c0952c06 100644 --- a/public/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README_react.html +++ b/public/JavaScript/2624. Snail Traversal/Claude Code Sonnet 4.5/README_react.html @@ -1155,9 +1155,9 @@

    実装方法の比較< - - - + + + diff --git a/public/JavaScript/2627. Debounce/Claude Code Sonnet 4.5 extended/README_react.html b/public/JavaScript/2627. Debounce/Claude Code Sonnet 4.5 extended/README_react.html index db4fe325..72a1c045 100644 --- a/public/JavaScript/2627. Debounce/Claude Code Sonnet 4.5 extended/README_react.html +++ b/public/JavaScript/2627. Debounce/Claude Code Sonnet 4.5 extended/README_react.html @@ -796,13 +796,13 @@

    実装比較

    src="/vendor/prismjs/components/prism-python.min.js" > diff --git a/public/JavaScript/2629. Function Composition/Claude Code Sonnet 4.6 extended/README_react.html b/public/JavaScript/2629. Function Composition/Claude Code Sonnet 4.6 extended/README_react.html index 38b0bbff..ebbf0fc7 100644 --- a/public/JavaScript/2629. Function Composition/Claude Code Sonnet 4.6 extended/README_react.html +++ b/public/JavaScript/2629. Function Composition/Claude Code Sonnet 4.6 extended/README_react.html @@ -33,13 +33,23 @@ src="/vendor/prismjs/components/prism-typescript.min.js" > + - - - + + + - - - + + +