Skip to content

Commit dac71af

Browse files
committed
fix(translate_only): fix HTML output directory and clean LLM artifacts
- Use correct HTML output dir from config instead of same dir as MD - Add clean_translated_content() to remove LLM artifacts (---, ```, empty lines) - Share cleanup function between translate_only.py and main pipeline
1 parent a6ff414 commit dac71af

File tree

6 files changed

+461
-69
lines changed

6 files changed

+461
-69
lines changed
Lines changed: 332 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,332 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>NeetCode Agent Evolved Mindmap (ZH-TW) - NeetCode Mind Maps</title>
7+
<style>
8+
* { margin: 0; padding: 0; box-sizing: border-box; }
9+
html, body { height: 100%; }
10+
.markmap { width: 100%; height: 100%; }
11+
.markmap > svg { width: 100%; height: 100%; }
12+
#topbar {
13+
position: fixed; top: 0; left: 0; right: 0; z-index: 100;
14+
background: #fff; border-bottom: 1px solid #e5e7eb;
15+
padding: 8px 16px; display: flex; gap: 8px;
16+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
17+
font-size: 13px;
18+
}
19+
#topbar button {
20+
padding: 4px 12px; border: 1px solid #d1d5db;
21+
border-radius: 4px; background: #fff; cursor: pointer;
22+
}
23+
#topbar button:hover { background: #f3f4f6; }
24+
.markmap { margin-top: 40px; height: calc(100% - 40px); }
25+
</style>
26+
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
27+
<script src="https://cdn.jsdelivr.net/npm/markmap-view"></script>
28+
<script src="https://cdn.jsdelivr.net/npm/markmap-lib"></script>
29+
<script src="https://cdn.jsdelivr.net/npm/markmap-toolbar"></script>
30+
<script>
31+
function fitView() {
32+
var svg = document.querySelector('.markmap > svg');
33+
if (svg && svg.mm) svg.mm.fit();
34+
}
35+
function expandAll() {
36+
var svg = document.querySelector('.markmap > svg');
37+
if (svg && svg.mm) {
38+
var root = svg.mm.state.data;
39+
(function expand(n) {
40+
n.payload = Object.assign({}, n.payload, { fold: 0 });
41+
if (n.children) n.children.forEach(expand);
42+
})(root);
43+
svg.mm.setData(root); svg.mm.fit();
44+
}
45+
}
46+
function collapseAll() {
47+
var svg = document.querySelector('.markmap > svg');
48+
if (svg && svg.mm) {
49+
var root = svg.mm.state.data;
50+
root.children && root.children.forEach(function collapse(n) {
51+
if (n.children && n.children.length) {
52+
n.payload = Object.assign({}, n.payload, { fold: 1 });
53+
n.children.forEach(collapse);
54+
}
55+
});
56+
svg.mm.setData(root); svg.mm.fit();
57+
}
58+
}
59+
document.addEventListener('DOMContentLoaded', function() {
60+
const { Transformer, Markmap } = window.markmap;
61+
const transformer = new Transformer();
62+
const markdown = `\`\`\`markdown
63+
---
64+
title: LeetCode Patterns Knowledge Graph (33 Problems) — API Kernels → Patterns → Problems 🎯
65+
markmap:
66+
colorFreezeLevel: 2
67+
maxWidth: 300
68+
---
69+
70+
## 🎯 如何使用這個思維導圖(快速)
71+
- **自上而下閱讀**: *API Kernel* → *Pattern* → *Problems* (鏈接)
72+
- **練習循環**: 實現模板 → 解決 2–3 個問題 → 重構為可重用的 \`solve(pattern_state_machine)\` 心智模型
73+
- **進度追蹤**
74+
- [ ] 先完成所有 **簡單** 題目
75+
- [ ] 然後是 **中等** 變體
76+
- [ ] 最後是 **困難** “邊界情況放大器”
77+
78+
---
79+
80+
## 🧠 API 核心(“引擎”)
81+
### SubstringSlidingWindow — *一維窗口狀態機*
82+
- ==核心不變性==: 窗口 \`[L,R]\` 通過 **向右擴展** + **向左收縮** 保持有效
83+
- 複雜度: 通常 $O(n)$ 時間,$O(\\Sigma)$ 空間(字母表 / 不同鍵)
84+
85+
<!-- markmap: fold -->
86+
#### 模式速查表(來自文檔)
87+
| 問題 | 不變性 | 狀態 | 窗口大小 | 目標 |
88+
|---------|-----------|-------|-------------|------|
89+
| [LeetCode 3 - Longest Substring Without Repeating Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0003_longest_substring_without_repeating_characters.py) | 全部唯一 | 最後索引映射 | 可變 | 最大 |
90+
| [LeetCode 340 - Longest Substring with At Most K Distinct Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0340_longest_substring_with_at_most_k_distinct.py) | ≤K 不同 | 頻率映射 | 可變 | 最大 |
91+
| [LeetCode 76 - Minimum Window Substring](https://github.com/lufftw/neetcode/blob/main/solutions/0076_minimum_window_substring.py) | 覆蓋 \`t\` | 需要/擁有 | 可變 | 最小 |
92+
| [LeetCode 567 - Permutation in String](https://github.com/lufftw/neetcode/blob/main/solutions/0567_permutation_in_string.py) | 精確頻率匹配 | 頻率 + 匹配 | 固定 | 存在 |
93+
| [LeetCode 438 - Find All Anagrams in a String](https://github.com/lufftw/neetcode/blob/main/solutions/0438_find_all_anagrams_in_a_string.py) | 精確頻率匹配 | 頻率 + 匹配 | 固定 | 全部 |
94+
| [LeetCode 209 - Minimum Size Subarray Sum](https://github.com/lufftw/neetcode/blob/main/solutions/0209_minimum_size_subarray_sum.py) | 和 ≥ 目標 | 整數和 | 可變 | 最小 |
95+
96+
#### 模式
97+
- **sliding_window_unique** *(最大化,“跳左”優化)*
98+
- 🎯 問題
99+
- [ ] [LeetCode 3 - Longest Substring Without Repeating Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0003_longest_substring_without_repeating_characters.py)
100+
- 關鍵狀態: \`last_seen[char]\` → \`L = max(L, last_seen[c]+1)\`
101+
- **sliding_window_at_most_k_distinct** *(最大化,無效時收縮)*
102+
- 🎯 問題
103+
- [ ] [LeetCode 340 - Longest Substring with At Most K Distinct Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0340_longest_substring_with_at_most_k_distinct.py)
104+
- 關鍵不變性: \`len(freq) <= k\`
105+
- **sliding_window_freq_cover** *(覆蓋 / 精確匹配家族)*
106+
- 🎯 問題
107+
- [ ] [LeetCode 76 - Minimum Window Substring](https://github.com/lufftw/neetcode/blob/main/solutions/0076_minimum_window_substring.py) — *在有效時最小化*
108+
- [ ] [LeetCode 438 - Find All Anagrams in a String](https://github.com/lufftw/neetcode/blob/main/solutions/0438_find_all_anagrams_in_a_string.py) — *固定窗口,收集索引*
109+
- [ ] [LeetCode 567 - Permutation in String](https://github.com/lufftw/neetcode/blob/main/solutions/0567_permutation_in_string.py) — *固定窗口,布林值*
110+
- **sliding_window_cost_bounded** *(數值約束)*
111+
- 🎯 問題
112+
- [ ] [LeetCode 209 - Minimum Size Subarray Sum](https://github.com/lufftw/neetcode/blob/main/solutions/0209_minimum_size_subarray_sum.py)
113+
- 典型要求: 正數 → 單調收縮有效
114+
115+
---
116+
117+
### TwoPointersTraversal — *序列上的指針編排*
118+
- ==核心不變性==: 指針確定性移動;已處理區域是“安全”的
119+
- 複雜度: 通常 $O(n)$ 時間,$O(1)$ 空間(排序步驟除外)
120+
121+
#### 模式比較(來自文檔)
122+
| 模式 | 指針初始化 | 移動 | 終止 | 時間 | 空間 | 關鍵用例 |
123+
|---------|--------------|----------|-------------|------|-------|--------------|
124+
| 相反方向 | \`0, n-1\` | 向中心 | \`L>=R\` | $O(n)$ | $O(1)$ | 排序對 / 回文 / 最大化 |
125+
| 同方向 | \`write, read\` | 向前 | \`read==n\` | $O(n)$ | $O(1)$ | 就地修改 |
126+
| 快慢指針 | \`slow, fast\` | 1× / 2× | 相遇或空 | $O(n)$ | $O(1)$ | 循環 / 中點 |
127+
| 去重枚舉 | \`i\` + \`L,R\` | 嵌套 | 完成 | $O(n^2)$ | $O(1)$ | 3Sum/4Sum |
128+
129+
#### 模式
130+
- **two_pointer_opposite_maximize**
131+
- 🎯 問題
132+
- [ ] [LeetCode 11 - Container With Most Water](https://github.com/lufftw/neetcode/blob/main/solutions/0011_container_with_most_water.py)
133+
- 洞察: 移動 **較短** 高度的指針
134+
- **two_pointer_three_sum** *(去重枚舉)*
135+
- 🎯 問題
136+
- [ ] [LeetCode 15 - 3Sum](https://github.com/lufftw/neetcode/blob/main/solutions/0015_3sum.py)
137+
- [ ] [LeetCode 16 - 3Sum Closest](https://github.com/lufftw/neetcode/blob/main/solutions/0016_3sum_closest.py)
138+
- 要求: 先排序 ($O(n\\log n)$),然後掃描去重
139+
- **two_pointer_opposite_palindrome**
140+
- 🎯 問題
141+
- [ ] [LeetCode 125 - Valid Palindrome](https://github.com/lufftw/neetcode/blob/main/solutions/0125_valid_palindrome.py)
142+
- [ ] [LeetCode 680 - Valid Palindrome II](https://github.com/lufftw/neetcode/blob/main/solutions/0680_valid_palindrome_ii.py)
143+
- **two_pointer_writer_dedup**
144+
- 🎯 問題
145+
- [ ] [LeetCode 26 - Remove Duplicates from Sorted Array](https://github.com/lufftw/neetcode/blob/main/solutions/0026_remove_duplicates_from_sorted_array.py)
146+
- [ ] [LeetCode 80 - Remove Duplicates from Sorted Array II](https://github.com/lufftw/neetcode/blob/main/solutions/0080_remove_duplicates_from_sorted_array_ii.py)
147+
- **two_pointer_writer_remove**
148+
- 🎯 問題
149+
- [ ] [LeetCode 27 - Remove Element](https://github.com/lufftw/neetcode/blob/main/solutions/0027_remove_element.py)
150+
- **two_pointer_writer_compact**
151+
- 🎯 問題
152+
- [ ] [LeetCode 283 - Move Zeroes](https://github.com/lufftw/neetcode/blob/main/solutions/0283_move_zeroes.py)
153+
154+
---
155+
156+
### FastSlowPointers — *Floyd + 中點 + 隱式序列*
157+
- ==核心不變性==: 如果存在循環,\`fast\` 會遇到 \`slow\`
158+
- 模式
159+
- **fast_slow_cycle_detect**
160+
- [ ] [LeetCode 141 - Linked List Cycle](https://github.com/lufftw/neetcode/blob/main/solutions/0141_linked_list_cycle.py)
161+
- **fast_slow_cycle_start**
162+
- [ ] [LeetCode 142 - Linked List Cycle II](https://github.com/lufftw/neetcode/blob/main/solutions/0142_linked_list_cycle_ii.py)
163+
- **fast_slow_midpoint**
164+
- [ ] [LeetCode 876 - Middle of the Linked List](https://github.com/lufftw/neetcode/blob/main/solutions/0876_middle_of_the_linked_list.py)
165+
- **fast_slow_implicit_cycle**
166+
- [ ] [LeetCode 202 - Happy Number](https://github.com/lufftw/neetcode/blob/main/solutions/0202_happy_number.py)
167+
168+
---
169+
170+
### TwoPointerPartition — *就地分區“迷你快速排序”*
171+
- ==核心不變性==: 區域按屬性分區
172+
- 模式
173+
- **dutch_flag_partition**
174+
- [ ] [LeetCode 75 - Sort Colors](https://github.com/lufftw/neetcode/blob/main/solutions/0075_sort_colors.py)
175+
- **two_way_partition**
176+
- [ ] [LeetCode 905 - Sort Array By Parity](https://github.com/lufftw/neetcode/blob/main/solutions/0905_sort_array_by_parity.py)
177+
- [ ] [LeetCode 922 - Sort Array By Parity II](https://github.com/lufftw/neetcode/blob/main/solutions/0922_sort_array_by_parity_ii.py)
178+
- **quickselect_partition** *(通過分區選擇)*
179+
- [ ] [LeetCode 215 - Kth Largest Element in an Array](https://github.com/lufftw/neetcode/blob/main/solutions/0215_kth_largest_element_in_an_array.py)
180+
181+
---
182+
183+
### MergeSortedSequences — *合併兩個排序序列*
184+
- ==核心不變性==: 輸出前綴完全排序
185+
- 模式
186+
- **merge_two_sorted_lists**
187+
- [ ] [LeetCode 21 - Merge Two Sorted Lists](https://github.com/lufftw/neetcode/blob/main/solutions/0021_merge_two_sorted_lists.py)
188+
- **merge_two_sorted_arrays**
189+
- [ ] [LeetCode 88 - Merge Sorted Array](https://github.com/lufftw/neetcode/blob/main/solutions/0088_merge_sorted_array.py)
190+
- **merge_sorted_from_ends**
191+
- [ ] [LeetCode 977 - Squares of a Sorted Array](https://github.com/lufftw/neetcode/blob/main/solutions/0977_squares_of_a_sorted_array.py)
192+
193+
---
194+
195+
### KWayMerge — *合併 K 個排序序列*
196+
- 兩種主要實現
197+
- **merge_k_sorted_heap** → $O(N\\log k)$ 時間,$O(k)$ 堆
198+
- **merge_k_sorted_divide** → $O(N\\log k)$ 時間,有時較小的常數
199+
- 🎯 問題
200+
- [ ] [LeetCode 23 - Merge k Sorted Lists](https://github.com/lufftw/neetcode/blob/main/solutions/0023_merge_k_sorted_lists.py)
201+
- 相關“混合思維”: [LeetCode 4 - Median of Two Sorted Arrays](https://github.com/lufftw/neetcode/blob/main/solutions/0004_median_of_two_sorted_arrays.py)
202+
203+
---
204+
205+
### HeapTopK — *在流式更新中保持最佳 K*
206+
- 模式
207+
- **heap_kth_element**
208+
- [ ] [LeetCode 215 - Kth Largest Element in an Array](https://github.com/lufftw/neetcode/blob/main/solutions/0215_kth_largest_element_in_an_array.py)
209+
210+
---
211+
212+
### LinkedListInPlaceReversal — *指針手術*
213+
- 模式
214+
- **linked_list_k_group_reversal**
215+
- [ ] [LeetCode 25 - Reverse Nodes in k-Group](https://github.com/lufftw/neetcode/blob/main/solutions/0025_reverse_nodes_in_k_group.py)
216+
- 也包括核心鏈表運算
217+
- [ ] [LeetCode 2 - Add Two Numbers](https://github.com/lufftw/neetcode/blob/main/solutions/0002_add_two_numbers.py)
218+
219+
---
220+
221+
### BacktrackingExploration — *帶修剪的搜索樹*
222+
- 模式
223+
- **backtracking_n_queens**
224+
- [ ] [LeetCode 51 - N-Queens](https://github.com/lufftw/neetcode/blob/main/solutions/0051_n_queens.py)
225+
226+
---
227+
228+
### GridBFSMultiSource — *網格上的波前傳播*
229+
- 模式
230+
- **grid_bfs_propagation**
231+
- [ ] [LeetCode 994 - Rotting Oranges](https://github.com/lufftw/neetcode/blob/main/solutions/0994_rotting_oranges.py)
232+
- 實現不變性: 隊列持有當前“分鐘/層級”的前沿
233+
234+
---
235+
236+
## 🧭 路線圖切片(接下來要做什麼)
237+
### 滑動窗口精通 📚
238+
- [ ] [LeetCode 3 - Longest Substring Without Repeating Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0003_longest_substring_without_repeating_characters.py)
239+
- [ ] [LeetCode 340 - Longest Substring with At Most K Distinct Characters](https://github.com/lufftw/neetcode/blob/main/solutions/0340_longest_substring_with_at_most_k_distinct.py)
240+
- [ ] [LeetCode 209 - Minimum Size Subarray Sum](https://github.com/lufftw/neetcode/blob/main/solutions/0209_minimum_size_subarray_sum.py)
241+
- [ ] [LeetCode 567 - Permutation in String](https://github.com/lufftw/neetcode/blob/main/solutions/0567_permutation_in_string.py)
242+
- [ ] [LeetCode 438 - Find All Anagrams in a String](https://github.com/lufftw/neetcode/blob/main/solutions/0438_find_all_anagrams_in_a_string.py)
243+
- [ ] [LeetCode 76 - Minimum Window Substring](https://github.com/lufftw/neetcode/blob/main/solutions/0076_minimum_window_substring.py) 🔥
244+
245+
### 雙指針精通 ⚡
246+
- 相反指針
247+
- [ ] [LeetCode 11 - Container With Most Water](https://github.com/lufftw/neetcode/blob/main/solutions/0011_container_with_most_water.py)
248+
- [ ] [LeetCode 125 - Valid Palindrome](https://github.com/lufftw/neetcode/blob/main/solutions/0125_valid_palindrome.py)
249+
- [ ] [LeetCode 680 - Valid Palindrome II](https://github.com/lufftw/neetcode/blob/main/solutions/0680_valid_palindrome_ii.py)
250+
- 寫指針(就地)
251+
- [ ] [LeetCode 26 - Remove Duplicates from Sorted Array](https://github.com/lufftw/neetcode/blob/main/solutions/0026_remove_duplicates_from_sorted_array.py)
252+
- [ ] [LeetCode 27 - Remove Element](https://github.com/lufftw/neetcode/blob/main/solutions/0027_remove_element.py)
253+
- [ ] [LeetCode 283 - Move Zeroes](https://github.com/lufftw/neetcode/blob/main/solutions/0283_move_zeroes.py)
254+
- [ ] [LeetCode 80 - Remove Duplicates from Sorted Array II](https://github.com/lufftw/neetcode/blob/main/solutions/0080_remove_duplicates_from_sorted_array_ii.py)
255+
- 快慢指針
256+
- [ ] [LeetCode 141 - Linked List Cycle](https://github.com/lufftw/neetcode/blob/main/solutions/0141_linked_list_cycle.py)
257+
- [ ] [LeetCode 142 - Linked List Cycle II](https://github.com/lufftw/neetcode/blob/main/solutions/0142_linked_list_cycle_ii.py)
258+
- [ ] [LeetCode 876 - Middle of the Linked List](https://github.com/lufftw/neetcode/blob/main/solutions/0876_middle_of_the_linked_list.py)
259+
- [ ] [LeetCode 202 - Happy Number](https://github.com/lufftw/neetcode/blob/main/solutions/0202_happy_number.py)
260+
261+
---
262+
263+
## 🧩 “同一問題,不同視角” (遷移學習)
264+
- **選擇**: [LeetCode 215 - Kth Largest Element in an Array](https://github.com/lufftw/neetcode/blob/main/solutions/0215_kth_largest_element_in_an_array.py)
265+
- 選項 A: \`quickselect_partition\` (期望 $O(n)$)
266+
- 選項 B: \`heap_kth_element\` ($O(n\\log k)$,流式友好)
267+
- **合併**:
268+
- 2 路: [LeetCode 21 - Merge Two Sorted Lists](https://github.com/lufftw/neetcode/blob/main/solutions/0021_merge_two_sorted_lists.py), [LeetCode 88 - Merge Sorted Array](https://github.com/lufftw/neetcode/blob/main/solutions/0088_merge_sorted_array.py)
269+
- K 路: [LeetCode 23 - Merge k Sorted Lists](https://github.com/lufftw/neetcode/blob/main/solutions/0023_merge_k_sorted_lists.py)
270+
- “邊界 + 合併思維”: [LeetCode 4 - Median of Two Sorted Arrays](https://github.com/lufftw/neetcode/blob/main/solutions/0004_median_of_two_sorted_arrays.py)
271+
272+
---
273+
274+
## 🧱 最小可重用模板(心智 API)
275+
\`\`\`python
276+
# 滑動窗口(可變,最大化)
277+
def max_window(seq):
278+
state = {}
279+
L = 0
280+
ans = 0
281+
for R, x in enumerate(seq):
282+
add(state, x)
283+
while invalid(state):
284+
remove(state, seq[L]); L += 1
285+
ans = max(ans, R - L + 1)
286+
return ans
287+
288+
# 雙指針(相反)
289+
def opposite(arr):
290+
L, R = 0, len(arr) - 1
291+
while L < R:
292+
if should_move_left(arr, L, R):
293+
L += 1
294+
else:
295+
R -= 1
296+
\`\`\`
297+
298+
---
299+
\`\`\``;
300+
const { root } = transformer.transform(markdown);
301+
const svg = d3.select('.markmap').append('svg');
302+
const mm = Markmap.create(svg.node(), { color: (node) => node.payload?.color || '#f59e0b' }, root);
303+
svg.node().mm = mm;
304+
if (window.markmap && window.markmap.Toolbar) {
305+
const toolbar = new window.markmap.Toolbar();
306+
toolbar.attach(mm);
307+
setTimeout(function() {
308+
document.querySelectorAll('.mm-toolbar').forEach(function(toolbar) {
309+
toolbar.querySelectorAll('.mm-toolbar-item').forEach(function(item) {
310+
if ((item.title || '').toLowerCase().includes('dark')) item.remove();
311+
});
312+
var brand = toolbar.querySelector('.mm-toolbar-brand');
313+
if (brand) {
314+
brand.innerHTML = '🟡 NeetCode';
315+
brand.href = '#'; brand.onclick = function(e) { e.preventDefault(); };
316+
brand.style.fontSize = '12px'; brand.style.color = '#666';
317+
}
318+
});
319+
}, 200);
320+
}
321+
});
322+
</script>
323+
</head>
324+
<body>
325+
<div id="topbar">
326+
<button onclick="fitView()">Fit View</button>
327+
<button onclick="expandAll()">Expand All</button>
328+
<button onclick="collapseAll()">Collapse All</button>
329+
</div>
330+
<div class="markmap"></div>
331+
</body>
332+
</html>

0 commit comments

Comments
 (0)