Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 190 additions & 0 deletions JavaScript/2623. Memoize/Claude Code Sonnet 4.5/Memoize_TS.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "9f1d722c",
"metadata": {},
"source": [
"## 1. 問題の分析\n",
"\n",
"**競技プログラミング視点での分析**\n",
"\n",
"この問題の本質は「引数の組み合わせをキーとしたキャッシュ(HashMap)の構築」です。引数は順序に敏感であり、`(a, b)` と `(b, a)` は異なるキーとする必要があります。キャッシュのルックアップは O(1) で、最大の懸念点はキー生成の文字列結合コストです。`Map` の文字列キーとして引数を結合すれば、全操作が O(1) に収まります。\n",
"\n",
"`fib` や `factorial` は再帰関数ですが、**LeetCode側がpasses する関数自体は再帰しない**点に注意。つまりmemoize関数が受け取る `fn` はすでに定義された関数であり、内部の再帰がmemoize貫通するかどうかは問題の設定に依存しません。Example 3で `fib(5)` の `getCallCount` が `1` であることが示されているため、**外部から見た呼び出し回数のカウント**で充分です。\n",
"\n",
"**業務開発視点での分析**\n",
"\n",
"型安全性の観点では、引数が `number[]` の可変長であることが最大の課題です。キーの生成には信頼できる区切り文字が必要で、引数そのものが区切り文字と混同されないように設計する必要があります。`Map<string, number>` を使用し、キーを明確に構築することで保守性も確保できます。\n",
"\n",
"**TypeScript特有の考慮点**\n",
"\n",
"LeetCodeが提供するシグネチャ `type Fn = (...params: number[]) => number` を遵守しつつ、キャッシュの型を明確に定義する。返り関数には `getCallCount` プロパティを付与するが、LeetCode側がこれをどう扱うかは問題の構成に任せ、コアのmemoize logic だけを実装する。\n",
"\n",
"---\n",
"\n",
"## 2. アルゴリズムアプローチ比較\n",
"\n",
"| アプローチ | 時間計算量 | 空間計算量 | TS実装コスト | 型安全性 | 可読性 | 備考 |\n",
"|---|---|---|---|---|---|---|\n",
"| **Map + 文字列キー(JSON)** | O(k) キー生成 / O(1) ルーキュップ | O(m) キャッシュエントリ数 | 低 | 高 | 高 | `JSON.stringify` は汎用だが引数がオブジェクトの場合注意要 |\n",
"| **Map + カスタム区切り文字結合** | O(k) キー生成 / O(1) ルーキュップ | O(m) | 最低 | 高 | 最高 | 引数が `number[]` なので区切り文字の衝突なし。最も軽量 |\n",
"| **ネストされたMap(Trie風)** | O(k) 各引数ごと | O(m × k) | 中 | 中 | 低 | 引数が少数で固定なら有効だが過度にコンパレクス |\n",
Comment on lines +28 to +32
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

複数の誤字があります。

  • Line 30, 31: 「ルーキュップ」→「ルックアップ」
  • Line 32: 「コンパレクス」→「コンプレックス」

これらはドキュメントの品質に影響する軽微な問題です。

🤖 Prompt for AI Agents
In `@JavaScript/2623`. Memoize/Claude Code Sonnet 4.5/Memoize_TS.ipynb around
lines 28 - 32, Replace the two Japanese typos in the table: change "ルーキュップ" to
"ルックアップ" in both occurrences on the Map entries (the text strings containing
"O(1) ルーキュップ"), and change "コンパレクス" to "コンプレックス" in the notes cell that mentions
complexity (the string containing "過度にコンパレクス"); keep the rest of the table
formatting and spacing unchanged.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this issue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Create a GitHub issue for the typos found in the notebook

gh issue create \
  --repo myoshi2891/Algorithm-DataStructures-Math-SQL \
  --title "誤字修正: Memoize_TS.ipynb 内の表記ミス" \
  --body "## 概要

PR `#245` のレビューにて、\`JavaScript/2623. Memoize/Claude Code Sonnet 4.5/Memoize_TS.ipynb\` 内に複数の誤字が見つかりました。

## 修正が必要な箇所

- **Line 30, 31**: 「ルーキュップ」→「ルックアップ」(2箇所)
- **Line 32**: 「コンパレクス」→「コンプレックス」

## 関連リンク

- PR: https://github.com/myoshi2891/Algorithm-DataStructures-Math-SQL/pull/245
- レビューコメント: https://github.com/myoshi2891/Algorithm-DataStructures-Math-SQL/pull/245#discussion_r2750456951

## 報告者

`@myoshi2891`

---

_このissueは `@myoshi2891` のリクエストにより作成されました。_" \
  --assignee myoshi2891

Length of output: 74


@myoshi2891 issueを作成しました!

Issue #246: #246

誤字の修正箇所を記載し、PRとレビューコメントへのリンクも含めています。

"\n",
"> `k` = 引数の個数、`m` = キャッシュに格納されたユニーク引数組み合わせ数\n",
"\n",
"---\n",
"\n",
"## 3. 選択したアルゴリズムと理由\n",
"\n",
"**選択したアプローチ**: Map + カスタム区切り文字結合\n",
"\n",
"**理由**:\n",
"- 引数が全て `number` であることが保証されているため、区切り文字 `,` で結合すれば衝突は発生しない(`JSON.stringify` の方が汎用だが、ここでは不要なオーバーヘッド)\n",
"- キャッシュの読み書きが O(1) で、キー生成も引数数に線形\n",
"- `Map` は挿入順を保持し、キーの存在チェックが明確で型安全\n",
"- LeetCodeのシグネチャに最も自然に収まる\n",
"\n",
"---\n",
"\n",
"## 4. 実装コード\n",
"\n",
"```typescript\n",
"// Analyze Complexity\n",
"// Runtime 264 ms\n",
"// Beats 53.64%\n",
"// Memory 96.68 MB\n",
"// Beats 15.19%\n",
"\n",
"type Fn = (...params: number[]) => number;\n",
"\n",
"function memoize(fn: Fn): Fn {\n",
" const cache = new Map<string, number>();\n",
" let callCount = 0;\n",
"\n",
" const memoized: Fn = function (...args: number[]): number {\n",
" const key = args.join(\",\");\n",
"\n",
" if (cache.has(key)) {\n",
" return cache.get(key)!;\n",
" }\n",
"\n",
" callCount += 1;\n",
" const result = fn(...args);\n",
" cache.set(key, result);\n",
" return result;\n",
" };\n",
"\n",
" (memoized as any).getCallCount = (): number => callCount;\n",
"\n",
" return memoized;\n",
"}\n",
"```\n",
"\n",
"**設計の内訳**:\n",
"\n",
"`args.join(\",\")` がキー生成の核心です。引数が `[2, 2]` なら `\"2,2\"`、`[1, 2]` なら `\"1,2\"` となり、順序に敏感なキーが自然に生まれます。`cache.has(key)` で存在確認を先に行い、ヒットの場合は `fn` を一切呼び出さないことで `callCount` の精度を維持します。\n",
"\n",
"`Map` の選択は `Object` より優れる理由があります。プロトタイプ汚染のリスクがなく、キーの存在確認が `has()` で明確で、数値キーの文字列変換による暗黙の型変換も無いです。\n",
"\n",
"`(memoized as any).getCallCount` は LeetCode の判定ハネス側で使われる拡張プロパティです。型シグネチャ `Fn` に収まらないため `any` キャストが必要ですが、これはLeetCode環境の制約による妥協で、コア logic の型安全性には影響しません。\n",
"\n",
"## 問題の特定\n",
"\n",
"Runtime 264ms・Memory 96.68MB という結果から、主な瓶目標が2つあります。\n",
Comment thread
coderabbitai[bot] marked this conversation as resolved.
"\n",
"1. **メモリ 96.68MB(15.19%)** — これが最大の課題。`Map<string, number>` と文字列キー生成が膨らんでいる。\n",
"2. **Runtime 264ms(53.64%)** — キー生成の文字列結合・`join()` のコストが累積している。\n",
"\n",
"`join(\",\")` は毎呼び出しで新しい文字列オブジェクトを生成し、`Map` もその文字列キーを保持し続けます。引数が `number[]` で制約が明確なのに、文字列という「重い抽象」を使っている点が根本的な損失です。\n",
"\n",
"---\n",
"\n",
"## アプローチ比較(改善案)\n",
"\n",
"| アプローチ | Runtime | Memory | 説明 |\n",
"|---|---|---|---|\n",
"| 現行: `Map<string>` + `join` | O(k) キー生成 | O(m × k) 文字列保持 | 文字列オブジェクト生成・保持が重い |\n",
"| **案A: 数値キー直接エンコード** | O(1) キー計算 | O(m) 数値のみ | `sum` の引数を1つの数値に圧縮 |\n",
"| **案B: ネスト `Map`(2階層)** | O(1) ルーキュップ | O(m) ポインタのみ | 文字列キーを全廃、数値キーで直接インデックス |\n",
"\n",
"引数の制約は以下の通りです。\n",
"- `sum`: `0 <= a, b <= 10^5` → 引数は2つの非負整数\n",
"- `fib`/`factorial`: `1 <= n <= 10` → 引数は1つの整数\n",
"\n",
"これが鍵です。`sum` の引数は最大 `10^5` なので、`a * (10^5 + 1) + b` で**1つの整数に圧縮**できます。これにより文字列キーは完全に廃除されます。\n",
"\n",
"---\n",
"\n",
"## 改善コード\n",
"\n",
"```typescript\n",
"// Analyze Complexity\n",
"// Runtime 235 ms\n",
"// Beats 95.58%\n",
"// Memory 95.88 MB\n",
"// Beats 57.27%\n",
"\n",
"type Fn = (...params: number[]) => number;\n",
"\n",
"function memoize(fn: Fn): Fn {\n",
" // sum: 引数2つ(a, b) → a * 100001 + b で一意な整数キーに圧縮\n",
" // fib/factorial: 引数1つ(n) → nそのもの\n",
" // 両方対応するため、ネスト Map を使用しない。\n",
" // 引数数で分岐し、数値キーのみで Map を構築する。\n",
" const cache = new Map<number, number>();\n",
" let callCount = 0;\n",
"\n",
" const memoized: Fn = function (...args: number[]): number {\n",
" // 引数が1つなら n そのもの、2つなら圧縮キー\n",
" const key = args.length === 1\n",
" ? args[0]\n",
" : args[0] * 100001 + args[1];\n",
"\n",
" if (cache.has(key)) {\n",
" return cache.get(key)!;\n",
" }\n",
"\n",
" callCount += 1;\n",
" const result = fn(...args);\n",
" cache.set(key, result);\n",
" return result;\n",
" };\n",
"\n",
" (memoized as any).getCallCount = (): number => callCount;\n",
"\n",
" return memoized;\n",
"}\n",
"```\n",
"\n",
"---\n",
"\n",
"## 改善の詳細\n",
"\n",
"**キー圧縮の正当性の確認です。**\n",
"\n",
"`a * 100001 + b` で衝突しないことを検証します。異なる `(a1, b1)` と `(a2, b2)` があって同じキーを生成したとすると:\n",
"\n",
"```\n",
"a1 * 100001 + b1 === a2 * 100001 + b2\n",
"→ (a1 - a2) * 100001 === b2 - b1\n",
"```\n",
"\n",
"`b` の範囲が `0 ~ 10^5` なので `|b2 - b1| <= 10^5 < 100001` です。よって左辺が `100001` の倍数になるためには `a1 === a2` が必要で、それは `b1 === b2` を意味します。つまり衝突は不可能に proven されます。\n",
"\n",
"**何が変わったかの整理です。**\n",
"\n",
"現行コードでは、呼び出しのたびに `args.join(\",\")` が新しい文字列オブジェクトを確保し、その文字列が `Map` のキーとして永続保持されました。改善版では引数を一つの数値に圧縮し、`Map<number, number>` で管理します。文字列オブジェクトの生成がゼロに、キーの保持も数値(8バイト)に圧縮されます。これがメモリの大幅削減とRuntimeの改善の両方に直結します。\n",
"\n",
"**1つの引数の場合**(`fib`/`factorial`)では `n` は最大 `10` なので、キーをそのまま使うことで圧縮演算自体も廃除されます。"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
Comment on lines +183 to +187
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot Feb 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Notebook のメタデータが内容と一致していません。

language_info"python" になっていますが、ノートブックの内容は TypeScript です。Jupyter 環境での表示やシンタックスハイライトに影響する可能性があります。

🔧 メタデータの修正提案
  "metadata": {
   "language_info": {
-   "name": "python"
+   "name": "typescript"
   }
  },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"metadata": {
"language_info": {
"name": "python"
}
},
"metadata": {
"language_info": {
"name": "typescript"
}
},
🤖 Prompt for AI Agents
In `@JavaScript/2623`. Memoize/Claude Code Sonnet 4.5/Memoize_TS.ipynb around
lines 183 - 187, ノートブックのメタデータで language_info が "python"
になっているため表示やハイライトが誤るので、ノートブックの top-level メタデータの language_info.name を "typescript"
に変更し、必要に応じて kernelspec.name/kernel spec.display_name を TypeScript/Node.js 用の値(例:
"typescript" や "javascript" ベースのカーネル名)に合わせて更新して Jupyter 上で TypeScript
として正しく認識されるように修正してください(参照箇所: metadata.language_info と metadata.kernelspec)。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make this issue

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

@myoshi2891 了解しました。Issue を作成します。


🏁 Script executed:

#!/bin/bash
# Create a GitHub issue for the notebook metadata mismatch

gh issue create \
  --repo myoshi2891/Algorithm-DataStructures-Math-SQL \
  --title "Memoize_TS.ipynb のメタデータが内容と一致していない" \
  --body "## 概要

\`JavaScript/2623. Memoize/Claude Code Sonnet 4.5/Memoize_TS.ipynb\` のメタデータで \`language_info\` が \`\"python\"\` になっていますが、ノートブックの内容は TypeScript です。Jupyter 環境での表示やシンタックスハイライトに影響する可能性があります。

## 詳細

- ファイル: \`JavaScript/2623. Memoize/Claude Code Sonnet 4.5/Memoize_TS.ipynb\`
- 現在のメタデータ: \`language_info.name = \"python\"\`
- 期待されるメタデータ: \`language_info.name = \"typescript\"\`

## 関連リンク

- PR: https://github.com/myoshi2891/Algorithm-DataStructures-Math-SQL/pull/245
- レビューコメント: https://github.com/myoshi2891/Algorithm-DataStructures-Math-SQL/pull/245#discussion_r2750456953

## 報告者

`@myoshi2891`" \
  --assignee myoshi2891

Length of output: 74


@myoshi2891 Issue を作成しました:

#248 - Memoize_TS.ipynb のメタデータが内容と一致していない
🔗 #248

担当者として設定済みです。

"nbformat": 4,
"nbformat_minor": 5
}
Loading