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
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ Read this file end to end before touching anything.
with a 中文 toggle, so user-facing copy is authored as `{ en, zh }` pairs
(type `Loc<T>` from `lib/i18n.tsx`) — never English-only, never Chinese-only.
- Chinese inside a `zh:` value is content, not a comment. Never "clean it up".
- Keep a Chinese sentence in JSX on one line, or break it only next to a tag or
a `{…}` expression. JSX joins the lines of a text block with a space, and
Chinese shows it as a stray gap ("算。 建议"). Spaces belong only between
Chinese and Latin letters, digits or expressions ("第 3 章", "O(1) 随机访问"),
around "——" and around math operators — never after full-width punctuation.
`test/unit/zh-copy-spacing.test.ts` fails on any other.

## What this is

Expand Down
372 changes: 104 additions & 268 deletions app/advanced/page.tsx

Large diffs are not rendered by default.

38 changes: 12 additions & 26 deletions app/advanced/viz.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ export function LRUAnatomy() {
}
zh={
<>
哈希表存的不是值,而是<b>链表节点的引用</b>:查找交给哈希(不用遍历链表),
顺序交给链表(不用扫描哈希)—— 两个结构各自只负责自己那部分 O(1) 的工作。
哈希表存的不是值,而是<b>链表节点的引用</b>:查找交给哈希(不用遍历链表),顺序交给链表(不用扫描哈希)—— 两个结构各自只负责自己那部分 O(1) 的工作。
</>
}
/>
Expand Down Expand Up @@ -251,8 +250,7 @@ export function LRULab() {
}
zh={
<>
put({k},{v}):哈希表里已有 {k} → O(1) 拿到节点引用,原地改值,
再把节点<b>搬到头部</b>(它刚被用过,变成最新)。
put({k},{v}):哈希表里已有 {k} → O(1) 拿到节点引用,原地改值,再把节点<b>搬到头部</b>(它刚被用过,变成最新)。
</>
}
/>,
Expand Down Expand Up @@ -301,8 +299,7 @@ export function LRULab() {
}
zh={
<>
新节点 {k}:{v} 挂到<b>链表头部</b>(最新),哈希表写入 {k} → 节点引用。
整个 put 没有出现任何一次 O(n) 扫描。
新节点 {k}:{v} 挂到<b>链表头部</b>(最新),哈希表写入 {k} → 节点引用。整个 put 没有出现任何一次 O(n) 扫描。
</>
}
/>,
Expand Down Expand Up @@ -330,8 +327,7 @@ export function LRULab() {
}
zh={
<>
get({k}) = <b>-1</b>:哈希表 O(1) 查无此 key —— 链表碰都不用碰。
(它可能从未 put 过,也可能已经被淘汰了。)
get({k}) = <b>-1</b>:哈希表 O(1) 查无此 key —— 链表碰都不用碰。(它可能从未 put 过,也可能已经被淘汰了。)
</>
}
/>,
Expand Down Expand Up @@ -581,8 +577,7 @@ export function LFUBuckets() {
}
zh={
<>
每个桶是一条<b>按时间排序的链表</b>(桶内就是一个小 LRU);再配两张哈希表
(key → 值和频次、freq → 桶)和一个 minFreq 变量 —— 访问 = 从 freq 桶搬进
每个桶是一条<b>按时间排序的链表</b>(桶内就是一个小 LRU);再配两张哈希表(key → 值和频次、freq → 桶)和一个 minFreq 变量 —— 访问 = 从 freq 桶搬进
freq+1 桶,淘汰 = 移除 minFreq 桶里最老的。每一步都是 O(1)。
</>
}
Expand Down Expand Up @@ -709,10 +704,7 @@ export function SegAnatomy() {
}
zh={
<>
根节点 = 整个数组的和(24);每往下一层,区间<b>对半分</b>;叶子 = 单个元素。
[0,2] 这种奇数长度的区间就让左边多分一个:mid = (0+2)/2 = 1 → 左孩子 [0,1]、
右孩子 [2,2]。这棵树共 ⌈log₂6⌉ + 1 = 4 层,按边数算树高是 3,
所有操作都只沿着一条自顶向下的路径走。
根节点 = 整个数组的和(24);每往下一层,区间<b>对半分</b>;叶子 = 单个元素。[0,2] 这种奇数长度的区间就让左边多分一个:mid = (0+2)/2 = 1 → 左孩子 [0,1]、右孩子 [2,2]。这棵树共 ⌈log₂6⌉ + 1 = 4 层,按边数算树高是 3,所有操作都只沿着一条自顶向下的路径走。
</>
}
/>
Expand Down Expand Up @@ -932,8 +924,7 @@ export function SegLab() {
}
zh={
<>
sum({l},{r}) = <b>{sum}</b>:{pack.length} 个「整段被包住」的节点(绿色)直接给出答案,
黄色节点只是路过时被劈开 —— 访问节点数 O(log n),而不是把 {r - l + 1} 个叶子逐个相加。
sum({l},{r}) = <b>{sum}</b>:{pack.length} 个「整段被包住」的节点(绿色)直接给出答案,黄色节点只是路过时被劈开 —— 访问节点数 O(log n),而不是把 {r - l + 1} 个叶子逐个相加。
</>
}
/>,
Expand Down Expand Up @@ -1293,8 +1284,7 @@ const SKIP_FRAMES: SkipFrame[] = [
}
zh={
<>
L2 上 19 的右邻是 ∞ &gt; 23 —— 会走过头,于是<b>原地下楼</b>到 L1。
下一层节点更密,能走得更细。
L2 上 19 的右邻是 ∞ &gt; 23 —— 会走过头,于是<b>原地下楼</b>到 L1。下一层节点更密,能走得更细。
</>
}
/>
Expand Down Expand Up @@ -1348,8 +1338,7 @@ const SKIP_FRAMES: SkipFrame[] = [
}
zh={
<>
L0 上 19 的右邻是 23 = 23,<b>找到了。</b>全程只做了 4 次比较;
普通有序链表要从 3 开始一格格比。n 越大差距越大:
L0 上 19 的右邻是 23 = 23,<b>找到了。</b>全程只做了 4 次比较;普通有序链表要从 3 开始一格格比。n 越大差距越大:
<b>O(log n) vs O(n)</b>。
</>
}
Expand Down Expand Up @@ -1670,8 +1659,7 @@ export function BloomLab() {
}
zh={
<>
位 <b>{zero}</b> 还是 0 → <b>&quot;{word}&quot; 一定不在</b>。这是确定的:
如果它插入过,这一位必然已被置 1,而位从来不会被清零。
位 <b>{zero}</b> 还是 0 → <b>&quot;{word}&quot; 一定不在</b>。这是确定的:如果它插入过,这一位必然已被置 1,而位从来不会被清零。
</>
}
/>,
Expand All @@ -1688,8 +1676,7 @@ export function BloomLab() {
}
zh={
<>
3 个位全是 1 → 报告「<b>可能在</b>」。这次它确实插入过(真阳性),
但布隆过滤器自己分辨不出来,它只看位。
3 个位全是 1 → 报告「<b>可能在</b>」。这次它确实插入过(真阳性),但布隆过滤器自己分辨不出来,它只看位。
</>
}
/>,
Expand Down Expand Up @@ -1738,8 +1725,7 @@ export function BloomLab() {
}
zh={
<>
在候选词表里暂时找不到假阳性 —— 位数组还太「空」。再插入一两个词
(位越满,误判率越高),然后再点我。
在候选词表里暂时找不到假阳性 —— 位数组还太「空」。再插入一两个词(位越满,误判率越高),然后再点我。
</>
}
/>,
Expand Down
Loading
Loading