Skip to content

Commit 91df329

Browse files
authored
Merge pull request #272 from myoshi2891/dev-from-macmini
feat: Add 2627. Debounce and move 1174. Immediate Food Delivery II to…
2 parents 9839a10 + d8cbb85 commit 91df329

6 files changed

Lines changed: 1992 additions & 0 deletions

File tree

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "a96e51ed",
6+
"metadata": {},
7+
"source": [
8+
"# TypeScript Debounce関数 実装\n",
9+
"\n",
10+
"## 1. 問題の分析\n",
11+
"\n",
12+
"### 競技プログラミング視点での分析\n",
13+
"- **実行速度**: debounce自体は遅延が目的なので、呼び出しのオーバーヘッドを最小化\n",
14+
"- **メモリ使用量**: タイマーID1つと最新の引数のみ保持(O(1)空間)\n",
15+
"- **アルゴリズム**: シンプルなタイマー管理で十分\n",
16+
"\n",
17+
"### 業務開発視点での分析\n",
18+
"- **型安全性**: 引数の型を正確に保持し、実行時エラーを防止\n",
19+
"- **保守性**: クロージャによる状態管理で明確な責務分離\n",
20+
"- **メモリリーク防止**: タイマーの適切なクリアが必須\n",
21+
"- **エラーハンドリング**: 不正な`t`値の検証\n",
22+
"\n",
23+
"### TypeScript特有の考慮点\n",
24+
"- **型推論**: `ReturnType<typeof setTimeout>`でタイマーIDの型を自動推論\n",
25+
"- **クロージャの型安全性**: 外部変数の型を厳密に管理\n",
26+
"- **ジェネリクス**: より汎用的な実装も可能だが、LeetCode形式に従う\n",
27+
"\n",
28+
"## 2. アルゴリズムアプローチ比較\n",
29+
"\n",
30+
"|アプローチ|時間計算量|空間計算量|TS実装コスト|型安全性|可読性|備考|\n",
31+
"|---------|---------|---------|-----------|-------|------|-----|\n",
32+
"|タイマー管理|O(1)|O(1)|低|高|高|標準的なdebounce実装|\n",
33+
"|キュー方式|O(n)|O(n)|高|中|低|過剰設計、不要|\n",
34+
"\n",
35+
"## 3. 選択したアルゴリズムと理由\n",
36+
"\n",
37+
"**選択したアプローチ**: タイマー管理方式\n",
38+
"\n",
39+
"**理由**:\n",
40+
"- **計算量的な優位性**: 各呼び出しO(1)、メモリもO(1)で最適\n",
41+
"- **TypeScript環境での型安全性**: クロージャで型情報を完全に保持\n",
42+
"- **保守性・可読性**: 実装が直感的で、debounceの動作が明確\n",
43+
"\n",
44+
"**TypeScript特有の最適化ポイント**:\n",
45+
"- `ReturnType<typeof setTimeout>`による型推論活用\n",
46+
"- strict nullチェックによる安全なタイマー管理\n",
47+
"- クロージャによる状態カプセル化"
48+
]
49+
},
50+
{
51+
"cell_type": "markdown",
52+
"id": "code-header",
53+
"metadata": {},
54+
"source": [
55+
"## 4. 実装コード\n",
56+
"\n",
57+
"### LeetCode Performance\n",
58+
"- Runtime: 48 ms (Beats 71.15%)\n",
59+
"- Memory: 54.18 MB (Beats 95.14%)"
60+
]
61+
},
62+
{
63+
"cell_type": "code",
64+
"execution_count": null,
65+
"id": "type-definition",
66+
"metadata": {},
67+
"outputs": [],
68+
"source": [
69+
"// Type definition for function signature\n",
70+
"type F = (...args: number[]) => void"
71+
]
72+
},
73+
{
74+
"cell_type": "code",
75+
"execution_count": null,
76+
"id": "debounce-implementation",
77+
"metadata": {},
78+
"outputs": [],
79+
"source": [
80+
"/**\n",
81+
" * 関数の実行をデバウンスする(遅延実行&キャンセル機能付き)\n",
82+
" * @param fn - デバウンス対象の関数\n",
83+
" * @param t - 遅延時間(ミリ秒)\n",
84+
" * @returns デバウンスされた関数\n",
85+
" * @complexity Time: O(1) per call, Space: O(1)\n",
86+
" */\n",
87+
"function debounce(fn: F, t: number): F {\n",
88+
" // タイマーIDを保持するクロージャ変数(型安全)\n",
89+
" let timeoutId: ReturnType<typeof setTimeout> | null = null;\n",
90+
" \n",
91+
" return function(...args: number[]): void {\n",
92+
" // 既存のタイマーをキャンセル(clearTimeoutはnull安全)\n",
93+
" clearTimeout(timeoutId);\n",
94+
" \n",
95+
" // 新しいタイマーをセット(t ミリ秒後に fn を実行)\n",
96+
" timeoutId = setTimeout(() => {\n",
97+
" fn(...args);\n",
98+
" }, t);\n",
99+
" };\n",
100+
"}"
101+
]
102+
},
103+
{
104+
"cell_type": "code",
105+
"execution_count": null,
106+
"id": "usage-example",
107+
"metadata": {},
108+
"outputs": [],
109+
"source": [
110+
"// Usage example\n",
111+
"const log = debounce(console.log, 100);\n",
112+
"log('Hello'); // cancelled\n",
113+
"log('Hello'); // cancelled\n",
114+
"log('Hello'); // Logged at t=100ms"
115+
]
116+
},
117+
{
118+
"cell_type": "markdown",
119+
"id": "explanation",
120+
"metadata": {},
121+
"source": [
122+
"## 5. 実装の詳細説明\n",
123+
"\n",
124+
"### コア機能\n",
125+
"\n",
126+
"1. **タイマー管理**\n",
127+
" - `timeoutId`変数で現在のタイマーを追跡\n",
128+
" - `clearTimeout`はnull/undefinedを安全に受け付ける\n",
129+
"\n",
130+
"2. **キャンセルメカニズム**\n",
131+
" - 新しい呼び出し時に既存タイマーを`clearTimeout`でクリア\n",
132+
" - これにより前の実行がキャンセルされる\n",
133+
"\n",
134+
"3. **遅延実行**\n",
135+
" - `setTimeout`で`t`ミリ秒後に元の関数を実行\n",
136+
" - 引数は最新の呼び出し時のものを使用\n",
137+
"\n",
138+
"### TypeScript型安全性のポイント\n",
139+
"\n",
140+
"```typescript\n",
141+
"// ✅ 型安全な実装\n",
142+
"let timeoutId: ReturnType<typeof setTimeout> | null = null;\n",
143+
"// - ReturnType: setTimeoutの戻り値型を自動推論\n",
144+
"// - | null: 初期状態を表現\n",
145+
"// - clearTimeout(null)は仕様上安全(no-op)\n",
146+
"\n",
147+
"// ✅ 引数の型保持\n",
148+
"return function(...args: number[]): void {\n",
149+
" // argsの型が明示的にnumber[]として保持される\n",
150+
"}\n",
151+
"```\n",
152+
"\n",
153+
"### 動作例の詳細\n",
154+
"\n",
155+
"**Example 1**: `t = 50ms`\n",
156+
"```\n",
157+
"50ms: dlog(1) → タイマーセット(100msに実行予定)\n",
158+
"75ms: dlog(2) → 前のタイマークリア、新タイマーセット(125msに実行)\n",
159+
"125ms: fn(2)実行\n",
160+
"```\n",
161+
"\n",
162+
"**Example 2**: `t = 20ms`\n",
163+
"```\n",
164+
"50ms: dlog(1) → タイマーセット(70msに実行予定)\n",
165+
"70ms: fn(1)実行\n",
166+
"100ms: dlog(2) → タイマーセット(120msに実行)\n",
167+
"120ms: fn(2)実行\n",
168+
"```\n",
169+
"\n",
170+
"## TypeScript固有の最適化観点\n",
171+
"\n",
172+
"### 型安全性の活用\n",
173+
"\n",
174+
"1. **コンパイル時エラー防止**\n",
175+
" - `timeoutId`の型で未初期化状態を安全に管理\n",
176+
" - strict modeでのnull安全性確保\n",
177+
"\n",
178+
"2. **型推論による開発効率**\n",
179+
" - `ReturnType<typeof setTimeout>`で環境依存の型を自動取得\n",
180+
" - Node.js/ブラウザ両方で動作\n",
181+
"\n",
182+
"3. **クロージャの型安全性**\n",
183+
" - 外部変数の型が明確で、スコープ管理が安全\n",
184+
"\n",
185+
"### パフォーマンス特性\n",
186+
"\n",
187+
"- **時間計算量**: O(1) - 各呼び出しは定数時間\n",
188+
"- **空間計算量**: O(1) - タイマーID1つのみ保持\n",
189+
"- **メモリリーク**: なし - タイマーは適切にクリアされる\n",
190+
"\n",
191+
"### エッジケース対応\n",
192+
"\n",
193+
"- `t = 0`: `setTimeout(fn, 0)`は次のイベントループティックで実行される(同期的ではない)。連続呼び出しでは最後の呼び出しのみが実行されるdebounce動作は維持される\n",
194+
"- 連続呼び出し: 最後の呼び出しのみが実行される\n",
195+
"- 引数なし: 正常に動作(`...args`が空配列)"
196+
]
197+
}
198+
],
199+
"metadata": {
200+
"kernelspec": {
201+
"display_name": "TypeScript",
202+
"language": "typescript",
203+
"name": "typescript"
204+
},
205+
"language_info": {
206+
"file_extension": ".ts",
207+
"mimetype": "text/typescript",
208+
"name": "typescript",
209+
"version": "5.3.3"
210+
}
211+
},
212+
"nbformat": 4,
213+
"nbformat_minor": 5
214+
}

0 commit comments

Comments
 (0)