交互式技术教程与实验
将算法、数据结构、CSS、浏览器机制等主题实现为可视化、可操作的页面—— 支持单步执行算法过程、调节参数观察结果、验证浏览器的实际行为。每个主题一个系列。
🧮算法与数据结构68
链表 Linked List
以放弃随机访问换 O(1) 就地增删:既拆解多指针单次遍历的经典题(反转 / 判环 / 合并 / 相交 / 深拷贝),也讲结构本身的变体(单 / 双 / 循环 / 跳表 / 展开 / XOR)。
动态数组与紧凑编码 Dynamic Array
一段连续内存装不下就换一段更大的——push 的摊还 O(1) 由此而来。Redis 把同一件事推到极致:一个数据类型配多种编码,元素少时用连续字节块,多了才换 dict 或 skiplist。四条线是扩容的摊还、SDS 与 intset 的头部设计、ziplist 连锁更新与 listpack 的修复,以及编码切换的阈值。
Bitmask 位运算的三类应用
同一个整数的二进制位,在集合成员 / 可达性指纹 / lane 占用三种场景中语义各异,共同点是以位运算替代遍历。
哈希表 Hash Table
以一次计算换一次查找:key 经散列函数变成数组下标,平均 O(1) 命中。四条线依次是散列函数的质量、两大类冲突解决、负载因子与扩容(含 Redis dict 的渐进式 rehash),以及现代实现的分组布局与分布式分片。
树 · 遍历 · 平衡 BST · 前缀 / 度量树
把树话题收拢到一处,分三条线:遍历(三序 × 递归 / 显式栈 / Morris)、平衡与查找 BST(红黑 / AVL / treap / 次优 BST)、走出 BST 的 radix tree 与 BK-tree。每类都配单步引擎,可改输入、单步播放。
B-tree · B+ tree · LSM-tree
数据不在内存里的时候,要省的不是比较次数而是页读次数。B-tree 靠高扇出把树压到三四层,B+ tree 把数据全挪到叶子并串成链,LSM-tree 干脆放弃原地更新、用顺序写加后台 compaction 换写入吞吐。三条线都在同一套代价模型下量。
Priority Queue 堆家族
每次出队优先级最高的元素。从二叉堆的 sift-up / sift-down 出发,走到 d 叉堆的树高与访存取舍、支撑 Dijkstra 的索引堆与 decrease-key、可并堆的 meld 一族,以及 Fibonacci heap 那条「理论最优却常输给二叉堆」的分界。
并查集 Union-Find
N 个对象不断合并、随时查询连通性——动态连通性问题。从 quick-find 逐步优化到 path compression,均摊复杂度接近 O(1)。
区间最值与 LCA
静态数组上问「这一段的最小值」,与树上问「这两个节点最近的公共祖先」,是同一个问题的两种形态。sparse table、倍增、欧拉序、Tarjan 离线与笛卡尔树,五条路径把两者来回归约。
空间索引 Spatial Index
一维排序索引答不了「这个矩形里有哪些点」。四个结构给出四种切法:uniform grid 等分平面、quadtree 按密度自适应细分、k-d tree 轮流按维度切、R-tree 索引矩形而非点;Morton code 与 geohash 则把二维压回一维,借 B+ tree 与 zset 完成查询。
持久化结构 Persistent
改一个元素而旧版本原样可用。手法是 path copying:只复制根到该位置这一条路径,其余子树按引用共享,于是一次修改花 O(log n) 空间。顺着这条线往下是主席树、HAMT、bit-partitioned vector、transient 与 RRB-tree。
文本缓冲 Text Buffer
编辑器把文件放在什么结构里。朴素字符串每敲一个字符要搬走整篇文档,1 MB 文档正中连续插入 1000 次实测搬移 10.5 亿字符。gap buffer 把空闲空间做成跟着光标走的洞,piece table 让原始文本从不被改写,rope 把文档挂上平衡树,三者各把这笔账压到不同的量级。
LFU Cache 频率淘汰缓存
容量满时淘汰累计访问最少的条目。朴素做法用 min-heap 是 O(log n);一篇 2010 论文用「频率链表 + bucket + hash 表」把 get / set / 淘汰全做到 O(1)。单步演示频率链表如何随访问移动,并和 LRU 并排对比。
缓存淘汰 Cache Eviction
容量满了该踢谁。命中率的上界是 Bélády 的离线最优,所有在线策略都在逼近它:CLOCK 用一个 reference bit 近似 LRU, ARC 用 ghost 列表自适应,W-TinyLFU 用 Count-Min sketch 做准入,S3-FIFO 与 SIEVE 用几条 FIFO 队列反超链表系,Redis 则宁可采样也不维护全局链表。
时间轮 Timing Wheel
管理海量定时器的 O(1) 结构:环形数组 + 槽位 bucket + 随 tick 前进的指针。单步演示定时器入槽、指针推进触发,以及分层时间轮如何用 cascade 降级避免「槽位膨胀」。
FastQueue 无锁环形队列 SPMC
高频交易里的纳秒级 SPMC ring buffer:两个单调 atomic counter 划出「可读区 / 写入区」,一次写入分「推进 W → 拷贝 → 推进 R」三步;再看 alignas 为何能消除 false sharing。
并发数据结构 Concurrent Structures
多个线程同时改一个结构,正确性判据换成 linearizability,效率判据换成进展保证。本系列用一台确定性交错模拟器把 CAS、ABA、Michael-Scott 队列、hazard pointer 与分片全部跑成可穷举的实验。
排列生成 字典序与回溯
把 n 个互异元素的全部 n! 个排列讲透:字典序下一个排列(支点 + 后继 + 翻转)、反复调用枚举全体、回溯递归树,以及康托展开把排列与整数序号一一对应。
自适应归并排序 Timsort 与 Powersort
现实数据多半基本有序。先识别天然 run 再合并它们,合并两段的代价约等于两段之和,于是合并顺序决定总代价。Timsort 用一套栈不变式(曾因不变式不成立而越界,CPython 补上了对栈顶第四段的检查),Powersort 改以虚拟二分树算 node power 定序,栈深上界一目了然且近最优。
排序 · 分区 / 下界 / 线性时间
quicksort 的全部难点在 partition:Lomuto 与 Hoare 的边界差别、pivot 选法、重复键上的三路切分、以及 introsort 用递归深度阈值兜底。再往上是 Ω(n log n) 这条比较排序下界与达到它的 heapsort, 往下是绕开下界的 counting / radix / bucket sort。
双指针 Two Pointer
当数据具有某种有序性时,两个单向移动的指针可将 O(n²) 降为 O(n)。分类讲解同向、对撞、快慢三种模式。
滑动窗口 Sliding Window
相邻窗口大部分重叠、仅相差一进一出,增量维护可降为单次遍历 O(n)。分定长(单调队列)与变长(可伸缩窗口)两类。
单调栈与单调队列 Monotonic Stack
栈里的元素保持单调,于是「谁把谁弹出去」这一个动作就定下了被弹者的答案。每个元素进栈一次出栈一次,一整类「往左右找第一个更大 / 更小」的问题因此降到 O(n)。往下接的是管辖区间与贡献法、定长窗口最值的 deque 形态,以及 deque 本身怎么实现。
二分查找 Binary Search
用一个循环不变量统一二分的全部变体:开区间 l = -1、r = n 加红蓝染色。四种边界查询只是两条判定乘两个返回端,同一套模板还能推广到单调谓词上的二分答案。
一维标签布局 1-D Label Placement
每个标签都有期望位置,数据密集时相互重叠。Kate Morley 的 O(n) 算法用 cluster 栈使最大偏移量最小化;竖直或水平轴通用。
弹幕排布 Danmaku Layout
滚动评论从右飞入,如何分配轨道、判定不追尾、轨道占满后如何降级。等速只看入场间距,变速归一则解追及不等式。
区间查询 前缀和 / 树状数组 / 线段树
在数组上反复执行区间查询与单点更新,五种能力递进的解法:前缀和、树状数组、线段树、lazy propagation 与区间合并,末页给出两个可交互的应用。
合并单元格 用四个坐标描述一块区域
合并区域通常以四个坐标(左上 + 右下)描述。解析数据模型、用矩形相交判定重叠,最终映射到锚点单元格与 rowspan/colspan。
Regex × Unicode 字符模型与自研引擎
一个「字符」往往由多个 code point 组成。先系统讲解 Unicode 字符模型与 \p{…} 属性,再用自研引擎解析 regex。
String Search KMP / BM / Rabin-Karp
在 text / pattern 对齐网格上观察 naive matching 的冗余比较,再分析 KMP / Boyer-Moore / Rabin-Karp 各自如何减少比较次数。
列表 diff 数组的最小差异更新
把一个列表变换为另一个最少需要多少次编辑操作?从 LCS、Myers(git diff)、LIS(框架 reconciler)到 virtual DOM 的工程权衡。
Suffix Automaton 后缀自动机
识别一个串全部子串的最小 DFA,却只需 ≤ 2n−1 个状态、O(n) 在线构造。核心是 endpos 等价类:结束位置相同的子串共用一个状态,suffix link 连成一棵 parent 树。单步看 sa_extend 逐字符建机(含 clone 分支),并把本质不同子串计数 / 出现次数 / 两串 LCS 都化作一次遍历。
连续重复消除 安排次序求最短
反复删除连续相同字符段、删后邻居贴合可级联,如何安排次序得到最短结果?从左贪心会错失「先删中间障碍、让远处同字符合并」的机会(abbbbccccbd 卡在 abd 而非 ad);改用区间 DP 判定子串可消空性 E(i,j),再在其上求最短 F,O(n³) 时间。
多重子集和 把两组数配对
两组数总和相等,要把数组2的碎片不重复地分进数组1的每个目标——整数化规避浮点 + 降序回溯 + 剩余和剪枝 + 同值去重,取代人工对账。
博弈论 收益矩阵 / minimax / 纳什均衡
从 2×2 收益矩阵出发:零和博弈的鞍点与 minimax、迭代消去支配策略、无鞍点时的混合策略,最后越过零和到纳什均衡与囚徒困境。
搜索 BFS / DFS / 回溯 / 剪枝
在庞大的状态空间中寻找一条路径。DFS(栈、深入到底再回溯)vs BFS(队列、首次到达终点即最短),再到回溯模板与剪枝。
Branch & Bound 分支限界
组合优化的解空间是 2ⁿ 规模的决策树。为子树估算乐观 bound,不优于已知最优解的子树整体剪除;末节说明 A* 是它的特例。
alpha-beta 剪枝减少博弈树的考察量
Minimax 在博弈树上推演,代价按 b^d 增长。搜索时沿途维护窗口 [α, β],一旦 α ≥ β,当前节点其余孩子可直接跳过。
Dancing Links 解 Exact Cover
数独 / N 皇后本质上是同一个 Exact Cover 问题。Knuth 的 Algorithm X + 双向循环链表使删除与还原均为 O(1)。
图论 · 从基础语言到现代结构理论
沿 Diestel 教材骨架铺开的图论 (graph theory) 定理体系:先把顶点 / 边 / 度 / 连通等基础语言说清楚,再过匹配 / 连通性 / 平面图 / 着色 / 流五类经典结构 (Hall / König / Menger / Euler / Kuratowski / max-flow min-cut),然后看极值 / Ramsey / Hamilton / 随机图这一族「整体条件逼出局部结构」的母题,最后落到无限图与图子式的现代结构理论。每页都把抽象定义落到一张能拖点、改参数、单步执行的图上。
图着色 · 从冲突建模到寄存器分配
把「互相冲突的东西不能拿同一份资源」翻译成冲突图 (conflict graph),资源数就是色数 χ。本系列沿算法与工程一条线走完图着色:先看排考这类问题怎么建模成着色,再看多项式启发式 (Welsh–Powell / smallest-last / DSATUR) 能把用色数压到哪,然后用回溯 + 剪枝求精确 χ,最后落到两个多项式可解的特例——区间图上的会议室分配,与编译器里的寄存器分配 (Chaitin 化简循环)。每页都能选图、单步执行、对照代码。
线性规划网络流 从最大流到 LP 对偶
从最大流的定义与残量网络出发,依次走完 Ford–Fulkerson / Edmonds–Karp / Dinic / ISAP / HLPP 这五种求解算法、最大流最小割定理、最小费用最大流,再到二分图匹配、带权匹配的顶标法、一般图的 blossom、经典建模归约、上下界网络流,最后用线性规划与对偶把整套理论统一收束。每页都能选网、单步播放、对照流量表与代码。
连通性算法 · SCC / 割点 / 2-SAT
一遍 DFS 记两个数——时间戳 dfn 与回溯值 low——就够同时解决三个问题:有向图的 strongly connected component、无向图的 articulation point 与 bridge、以及 2-SAT 的可满足性与构造。三页共用同一个 low-link 内核,各页都可单步播放:看 low 如何沿 DFS 树回传,以及判据在哪一帧成立。
random walk · PageRank 与图的谱
在图上随机走一步是最简单的图算法, 它的极限行为却同时是 PageRank、spectral clustering 与一批采样算法的共同底座。两页: 一页把网页的重要性定义成 random surfer 的 stationary distribution, 用 power iteration 逐轮算出来, 并处理 dangling node 与 spider trap 这两处会让极限失效的结构; 一页回到无向图本身, 从「极限分布正比于度数」这条一行可验的结论出发, 走到 hitting time、cover time、graph Laplacian 的谱与 effective resistance。
图论 · 最短路 / MST / 拓扑 / Euler / 差分约束 / 树分解
图 (graph) 上的经典算法合集:单步运行 Dijkstra 最短路与 Floyd/Johnson 全源最短路、Prim/Kruskal 最小生成树、Kahn/DFS 拓扑排序、Hierholzer 一笔画,再到差分约束与 treewidth 树分解。多数子页可选图、逐步播放并对照表格与代码; 树分解一页是静态交互(点 bag、拖规模), 没有帧播放。
最优分段 DP · 相册排版与内容分栏
把一维序列按顺序切成连续段,每段有代价,求全局最优切法。相册 justified layout(各段代价之和最小)与内容分栏均衡(min-max 切 K 段)共用同一套递推思路,各配贪心对照。
序列对齐 DP · 一张表跑出四种算法
LCS、编辑距离、Needleman–Wunsch 同属一个二维 DP:三方向转移 + max/min,换 spec 即换算法。附近亲 DTW:数值序列的时间轴对齐(字幕 forced alignment)。
DP 加速 · 省空间、稀疏性与 SMAWK
基本 DP 写出来只是起点:表格自身的结构还能再换一档时间或空间。本系列沿五种结构走:滚动数组丢了回溯路径,Hirschberg 分治在 O(m+n) 空间里把路径找回来;表格稀疏时只算 match point;最优 BST 的根位置单调,把 O(n³) 压到 O(n²);Monge 性质与 SMAWK 用 O(m+n) 找出全部行最小值;最后把 SMAWK 接回一维分段 DP,直方图分箱从 O(n²k) 降到 O(nk)。
背包问题九讲 动态规划专题
从 01 背包出发逐步增加约束、变换问法:完全 / 多重 / 混合 / 二维费用 / 分组 / 依赖,最终归纳为泛化物品与聚合算子替换。
树形 DP 后序聚合与拐弯路径
节点的答案依赖其全部子节点的答案,天然适合一次后序遍历。从求树高到直径、最大路径和与 House Robber III。
动画引擎原理 从插值到播放控制
不谈 CSS transition,而是从零拆解动画的底层要素:插值、缓动曲线、弹簧物理、关键帧与时间线编排、可回退的播放控制。每页都由本仓库手写的 @vega/anim 引擎实时驱动。
图片占位:主色与模糊预览
懒加载真图到达前先铺一块占位。最朴素的是一块主色——用八叉树把 24-bit 颜色空间逐位细分、折叠相近色取出主导色(并对比 median-cut 与 k-means);再往上一档, 把整张图压成 CSS-LQIP、BlurHash、ThumbHash 这类一团模糊预览。
平均数 是个最优解
「取平均」=「最小化距离平方和」。拖候选值看 cost 曲线在均值处触底,换惩罚换出 mean / median / midrange,再延伸到最小二乘回归。
Bloom Filter 布隆过滤器
概率型集合:判定「不存在」必然正确,判定「存在」可能误报。不存储元素本身,仅用一组 bit 与 k 个哈希函数置位。
概率型 sketch
一族用固定内存回答统计问题的结构:HyperLogLog 数不同的 key、Count-Min Sketch 数频次、Space-Saving 找 top-k、t-digest 报分位数、cuckoo filter 判成员且可删。共同点是内存与数据量无关,代价是一个有界的误差。
概率 条件概率 / 贝叶斯
用方阵(一个点 = 一个人)把 P(A | B) 展开成可计数的格子,推导贝叶斯定理,并复现基础比率导致的假阳性悖论。
Huffman 编码树
为什么「高频字符用短编码」能实现无损压缩?用 priority queue 单步建树、逐 bit 沿树解码,并展示其在 gzip / PNG / JPEG 中的应用。
分治 递归式 / master theorem / 随机化
分治算法的形状高度雷同, 区分它们的是代价。一条递归式 T(n) = aT(n/b) + f(n) 就装下了全部代价信息: 按 recursion tree 展开后, master theorem 的三种情形不过是在问代价压在树根、各层还是叶子。本系列先把这套框架讲清楚, 再走三个非排序的经典分治 (inversion 计数、快速幂、Karatsuba), 最后到随机化 —— quickselect 的期望线性、BFPRT 用来买断最坏的那笔钱, 以及 Las Vegas 与 Monte Carlo 的分野。
LZ77 滑动窗口压缩
把重复片段换成「往回 distance、抄 length 个」的回引。单步走一遍最长匹配编码、再把三元组流解码还原(含 length > distance 的重叠回引),并理解它如何与 Huffman 组成 DEFLATE(gzip / PNG)。
贪心 · 正确性的三种判据
贪心算法的代码没有难点,难的是判断它对不对。本系列把散落在各处的贪心实例收拢到一个问题下:一条局部选取规则,凭什么保证全局最优。三页分别给出三种判据——交换论证把「最优解可以一步步改造成贪心解」做成可执行的模板;Rado–Edmonds 定理给出 matroid 这一结构刻画,说明贪心对一切权函数最优的充要条件;最后一页落到调度与背包,用能跑出差值的反例划出贪心与 DP 的分界。
傅里叶变换 从级数到 FFT
足够规矩的信号都可分解为正弦波之和。一条主线:正弦分量 → 傅里叶级数 → 复指数 epicycle → DFT → FFT → 采样定理。
有限自动机 DFA / NFA / regex
状态机由一组状态与一张转移表给定。本系列介绍 DFA 与 NFA,并串起 regex → NFA → DFA → 最小 DFA 三个经典转换,外加反向的状态消去。
解析器 从字符流到语法树
解析是「把线性的字符流还原成有层次的树」。各台引擎按确定性与通用性分作四个象限,外加编辑器真正依赖的那半边:容错、诊断、无损语法树与增量。
图灵完备 从一条纸带到通用计算
无限纸带 + 读写头 + 指令表即可表达任何可计算函数。链路:图灵机 → 停机问题 → Brainfuck → Rule 110 → 意外图灵完备实例清单。
NP 完全性 · 判定、归约与近似
全站十几处正文写着「这是 NP-hard」,本系列补上这句话的地基:判定问题与 P / NP / co-NP 的分层,NP-hard 与 NP-complete 的区别,多项式时间归约怎么用(SAT → 3-SAT → independent set → vertex cover → clique 一条链走通),以及证明难了之后还能做什么——vertex cover 的 2-approximation、metric TSP 的 double-tree 与 Christofides、subset sum 的 FPTAS,连同不可近似性的边界。
Y 组合子 匿名函数的递归构造
lambda 演算中函数均为匿名,如何实现递归?用真实的 β-归约引擎逐步推导 Y = λf.(λx.f(x x))(λx.f(x x))。
稳定匹配 Gale–Shapley 与延迟接受
两组参与者按偏好配对至不存在 blocking pair。延迟接受机制:提议 + 暂时接受、遇更优提议则替换;man-optimal 定理揭示结果的不对称性。
配额分配 把整数名额按比例分下去
独立取整不守恒,饼图百分比因而凑不齐 100%。最大余额法 (Hamilton) 先取下整再按余数补齐缺口,代价是 Alabama 悖论;除数法 (D'Hondt / Sainte-Laguë) 逐席分配、单调无悖论,代价是放弃配额约束。
🧩谜题5
数独解题技巧 人类推理策略
规则只有一条,难点全在推理。将常见叫法对应到标准术语:hidden / naked single、X-Wing、着色、AIC,最后衔接回溯算法;末尾用同一套技巧阶梯给谜面定难度,配一个可以实战的对局页。
井字棋 OX 一个被完全解出的游戏
看似幼儿园游戏,却是博弈论里少数被完全解出的例子:双方最优必然平局。从可玩棋盘出发,看 minimax 如何向前看到底、为什么再也赢不了、不输的策略、整个状态空间有多大,最后用 WebRTC 做一个无后端也能跑的联机对战。
五子棋 连珠禁手与先手平衡
15×15 棋盘上「连成五子」的简单规则,藏着一个不舒服的事实:先手必胜。看自由规则为何失衡,连珠禁手(三三 / 四四 / 长连)与 Swap2 开局两条路怎么把先手抹平,顺便下一局、再用 WebRTC 做一个无后端的联机对战。
魔方的贴纸图 · 三束圆与转层
沿体对角线看过去,N 阶魔方的三族层平面各投影成一族平行线,六个面成六个 60° 菱形——只是前后两面叠在了一起。把每族平行线换成一束同心圆,每对圆交出两个点,前后随之分开:交点恰好 6N² 个,一个不多一个不少。转一层在图上就是绕一个圆心挪 N 个位置。可调 2 到 7 阶,与实体魔方联动。
国际象棋 实战对局
一个能真下的国际象棋盘:六档强度的 NPC (自研 negamax 加 alpha-beta,低档位以温度采样模拟人类失误),也可发一条链接与朋友直连对战 (WebRTC,不经服务器)。规则做全了 —— 王车易位、吃过路兵、升变,以及逼和、50 步、三次重复、子力不足四种和棋。另附一套八课的训练课与局后逐手复盘,每条结论都由这台引擎自己的实测数据背书。
🔢数学19
集合论 · 关系、运算与映射
集合是数学的通用底座。从 ∈ / ∉ 与 ⊆ / ⊂ 起,在 Venn 图上演示 ∪ ∩ − △ 与补集,再到基数 |A|、笛卡尔积 × 与幂集 P(A)、映射 f:A→B 的像与原像,最后用 {x | P(x)} 与 ∀ / ∃ 把集合与逻辑接起来。
实数 · 数系、小数展开与完备性
沿 ℕ ⊂ ℤ ⊂ ℚ ⊂ ℝ 的次序看四种数系,每一次扩张各自补上一种运算的封闭性。长除法的余数只有 q 种取值,鸽巢原理由此给出「有理数 ⟺ 有限或循环小数」,而循环节的长度等于 10 在模 q′ 下的乘法阶。无理数写不成分数,√2 有奇偶反证与无穷递降两条独立证明,有理根定理把结论推广到任意非完全平方数。完备性是压轴:确界原理在 ℚ 上失效,二分法在有理数域内永不终止。末页把这一整套抽象落到 double 上,那是一个约 1.84 × 10^19 元的有限集。
函数 · 性质与基本初等函数
从函数的概念(定义域、对应关系与值域)与图象变换起步,先看一条曲线整体的三条性质——单调性、奇偶性与最值;再逐个认识三类基本初等函数:幂函数 y = x^α、指数函数 y = aˣ 与它的反函数对数函数 y = log_a x;最后回到方程,用零点与二分法求近似解,比较三类函数的增长快慢,并拿函数去描述一组真实数据。
不等式 · 从性质到典型解法
先定住「变形时方向何时翻转」这条底线,再把「解不等式」翻译成「读函数图象的高低」:f(x) > 0 就是图象落在 x 轴上方的那段 x。解集,是这些 x 在横轴上的投影;一元二次、分式、绝对值与含参不等式都在这张图上收口。
三角函数 · 从角到波
把角讲清楚:角是一条射线绕原点旋转扫出的量,逆时针为正、顺时针为负,可以超过一整圈。弧度制用弧长度量角,让 π rad = 180°、弧长 s = rθ 这类公式退到最简;再放上单位圆,终边与圆的交点坐标就是 (cos θ, sin θ),旋转一圈把它「展开」便得到正弦、余弦与正切的曲线。同角关系与诱导公式则把任意角的求值一路化归到锐角。
解三角形 · 两条定理与它们的边界
三角形有六个元素:三条边与三个角。正弦定理 a/sin A = b/sin B = c/sin C = 2R 把边与它的对角绑在一起,余弦定理 c² = a² + b² − 2ab·cos C 则把一个角与三条边绑在一起。两条定理合起来,任给三个元素(三个角不算)就能解出其余三个——只有「两边及其中一边的对角」这一类会给出两组解,而两解的来历是圆与射线交了两个点。末两页处理派生量:面积的四个公式在细长三角形上分歧极大,以及仰角与方位角如何化归成解三角形。
平面向量 · 从有向线段到数量积
向量是既有大小又有方向的量:几何上是一条有向线段,代数上是一对坐标 (x, y)。本系列从加减、数乘等线性运算出发,落到基底与坐标表示,再到度量夹角与垂直的数量积 a·b,最后用这套运算去证几何命题、分解力。
复数 · 从 i² = −1 到旋转
给方程 x² = −1 一个解,数集扩到复数。一个复数 a + bi 就是复平面上的一个点,相等要求实部虚部同时相等,加减对应向量的平行四边形,而乘法把「模相乘、辐角相加」写进了几何:乘一个复数就是绕原点转一个角再伸缩一次。模 |z| 给出距离,于是 |z − z₀| = r 是圆、|z − z₁| = |z − z₂| 是中垂线。末页的 n 次单位根把圆等分成正 n 边形,那正是傅里叶变换里的旋转因子。
立体几何初步 · 形体、度量与位置关系
平面几何的对象在纸上,立体几何的对象在纸外——图只是投影,判据必须回到定义。本系列先枚举柱、锥、台、球的结构(顶点、棱、面与展开图),再给表面积与体积(同底等高的柱与锥体积比 3 : 1,台占柱的 (1 + k + k²)/3),然后处理点、线、面的位置关系:异面直线及其所成角,以及平行与垂直的判定与性质。每一页配一个可旋转的三维视图,不可见的棱按约定画虚线。
空间向量 · 用坐标与法向量解立体几何
平面向量加一个分量就是空间向量:坐标写成 (x, y, z),加减、数乘、数量积逐分量照旧。真正新增的只有两件事——混合积判三向量是否共面,以及法向量把平面装进一个向量里。有了它们,线面角、二面角、点面距、异面直线的距离全部退化成几次数量积与一次叉积,综合几何里那条要靠灵感找的辅助线,换成了一次线性代数。
直线与圆 · 方程、距离与位置关系
把「直线」与「圆」写成方程,几何问题随之变成代数计算。倾斜角与斜率量化倾斜程度(竖直线没有斜率),四种方程写法各有失效的情形而一般式 Ax + By + C = 0 没有例外;平行与垂直的判据落在系数上,点到直线的距离由一个公式给出。圆一侧从标准式与一般式的互换出发,再看直线与圆、圆与圆的位置关系——判据一律是距离与半径的比较。
圆锥曲线 · 三族的定义、离心率与联立
到两定点距离之和为定值给出椭圆,之差为定值给出双曲线,到一点与一线距离相等给出抛物线。三套定义由离心率接成一套:到焦点与到准线的距离之比恒为 e,e < 1 是椭圆、e = 1 是抛物线、e > 1 是双曲线,极坐标下三族共用 r = l/(1 + e·cos θ)。末尾处理直线与曲线的联立——判别式给公共点个数,而二次项系数为零那一支只有一个公共点却不是相切。
极坐标与参数方程 · 换一套坐标描述曲线
直角坐标不是描述平面的唯一办法。极坐标用「到极点的距离」与「转过的角」定位,圆、玫瑰线、圆锥曲线在这套坐标下的方程比直角坐标短得多:三族圆锥曲线甚至共用一个 rho = fracep1 - ecostheta,只差 e 的取值。代价是坐标不再唯一:同一个点有无穷多组 (rho, theta),「点是否在曲线上」与「两曲线交于何处」随之都不能只代一组坐标算。参数方程换的是另一个方向:不消去中间变量,而是让 x 与 y 各自随第三个变量走,摆线这类由运动定义的曲线因此才写得出来。
数列 · 等差等比、求和与归纳
数列是定义在正整数集上的函数,图象为一列孤立的点。等差数列由相邻两项之差恒定给出,通项是一次式、前 n 项和是无常数项的二次函数;等比数列由相邻两项之比恒定给出,求和公式在 q = 1 处须单列。本系列另收三种求和技巧(错位相减、裂项相消、分组),一阶线性递推的不动点法,以及数学归纳法的两步与它的边界。
导数 · 从变化率到极值与不等式
平均变化率是两点连线的斜率,让区间长度趋于零,割线的极限位置就是切线,它的斜率即导数 f′(x₀)。本系列从这个极限出发:先把基本初等函数的导数与和 / 积 / 商 / 复合四条法则备齐,再用导数的符号读出函数的升降,定出极值与闭区间上的最值,再把「作差、求导、比最小值」这条路线用到不等式的证明上;二阶导数补上曲线的弯曲方向与拐点,函数作图与实际的优化建模由此收束。
排列组合 · 计数、P(n,k) 与 C(n,k)
计数问题的两条主线:分步用乘法原理、分类用加法原理。在此之上,有序地取得到排列 P(n, k),无序地取得到组合 C(n, k),再由 Pascal 三角与二项式定理把组合数串成一张网。
概率与统计 · 从样本空间到成对数据
把概率还原成样本空间上「有利结果占多少」的计数,沿古典概型、事件运算与独立性、频率、条件概率一路推进到随机变量的分布列与期望方差,再到二项 / 超几何 / 正态三大分布;统计一侧从抽样与样本的数字特征起步,经用样本估计总体,收在成对数据的相关、回归与独立性检验。
几何 · 判定与构造
计算几何常见几类:点在多边形内(ray casting)、最近点对分治、贝塞尔控制点、Canvas/SVG 椭圆弧的两套参数、Sweep and Prune、Allen 区间代数、叉积定向、点集最小外接矩形(rotating calipers)。
Treemap 用面积铺满一块矩形
把一组带权重的项用矩形面积编码:面积 ∝ 权重、无重叠、铺满。难点不在铺满而在切成什么形状——从 slice-and-dice 的细长条到 squarify 的方正矩形(worst aspect ratio 贪心换行),再到层级嵌套 treemap。
⚛️物理3
力学 · 从描述运动到万有引力
力学的主线是三次换账本:先用位置、速度、加速度描述运动,再用 F=ma 追问加速度从哪来,最后发现同一个问题用功与能、用动量与冲量记账往往更省事。七组内容从一维直线运动一路铺到万有引力与人造卫星,公式始终只有那几条,换的是看问题的坐标与账本。
振动与波 · 从简谐运动到驻波
一个质点在平衡位置附近往复运动,是振动;这个振动被介质一站站传下去,是波。简谐运动给出振动最简单的形式 x(t)=Acos(omega t+varphi),机械波把它沿空间铺开,两列波相遇再叠加出干涉与驻波。全系列的对象都是周期性的状态,而不是一个质点从 A 到 B 的位移。
电磁学 · 从电场到交流电
电荷周围的空间被赋予一种性质,这就是场:电场强度 E=F/q 把作用力剥离了检验电荷本身。电荷动起来成为电流,电路把这套关系收进串并联与内阻;磁场对运动电荷施力,反过来磁通量的变化又生出电动势——这条回路闭合之处,正是发电机、变压器与整个电网的起点。
🎨CSS 与布局23
Logical Properties
物理属性 top / right / bottom / left 用固定的物理方向指代方位,不随书写模式改变;逻辑属性改用 block 轴与 inline 轴描述方位,两条轴的朝向由 writing-mode 决定,direction 再决定 inline 轴的哪一端是 start。讲轴模型、margin / padding / border 的 -block / -inline 写法、inset、inline-size / block-size,以及 text-align 与 float 的逻辑值——全程用 getComputedStyle 实测逻辑到物理的解析。
滚动的三个面:行为、滚动条外观、海量数据虚拟滚动
滚动有三个面。一面管滚动怎么动:overscroll-behavior(传播 / 回弹)、scroll-behavior(平滑)、scroll-axis-lock(斜向手势要不要被投影到单轴)、overflow-anchor(防内容跳动)、scroll snap(整齐吸附)、scroll-state 容器查询(读出贴顶 / 吸附 / 可滚态);一面管滚动条长什么样:::-webkit-scrollbar / DOM / Canvas 三档自定义;还有一面管装得下多少:用虚拟滚动在浏览器里滚动十亿乃至万亿行。每页一个可交互 demo。
How does CSS work 样式从哪来
未写任何 CSS 时 <h1> 已有更大字号与加粗——样式从何而来?四层链路:initial value → UA stylesheet → Normalize → Reset,用 getComputedStyle 实测。
CSS 自定义属性 var() 的解析与陷阱
--gap 是不折不扣的属性,只是值不被解析、先按原始 token 存着,var() 到 computed value time 才代换。讲 fallback、IACVT、@property 与空值开关。
CSS 函数 值是「算」出来的
大量属性值形如 name(参数),由浏览器求值得到最终值。14 类 115 个 value function 全景 + calc/min/max/clamp、round/mod/rem、tan(atan2()) 单位消除技巧,外加用 @function at-rule 定义你自己的带参函数。
Spacing 留白与间距
margin / padding / gutter / safe-area / grid / gap / line-height / letter-spacing / negative-space —— 设计与 CSS 里九种留白各自的名字与用途,逐个上手实测。
Flexbox 简写语义与对齐边界
两条主线:flex 简写如何展开成 grow/shrink/basis、flex: 1 的 basis 为何是 0% 而非 0、flex-basis vs width 优先级;以及对齐边界——居中溢出截断、safe center 回退、flex-wrap: balance。
CSS Grid 二维布局与轨道模型
把容器划成二维轨道网格再放置项。讲解 fr 如何分配剩余空间、minmax / repeat / auto-fill vs auto-fit、基于网格线的放置与 dense、grid-template-areas、两轴对齐,以及 subgrid / display: contents 两种跨容器对齐解,收束于「三列对齐列表」四种实现对照。
CSS Box Alignment 一套对齐属性横跨所有布局
对齐曾按布局各记一套:块级 margin: auto、表格 vertical-align、Flex 自带 justify-*。Box Alignment 把它抽象成一组与布局无关的属性,再由各模式规定生效范围与轴映射。
Inline 与 inline-block 的布局异常
负 margin-bottom 反而使元素下移、<img> 下方多出数像素、两个元素之间存在空隙——根源都在 IFC 的 line box 与 vertical-align baseline。
CSS stacking context 拆解
为什么 z-index:9999 有时仍被其他元素覆盖?核心规则、触发条件清单、isolation:isolate 与三个常见误区,实时查看真实 stacking order。
CSS Anchor Positioning 元素相对锚点定位
tooltip 与菜单要解决的都是「使 B 相对 A 定位」。纯 CSS 的实现是 anchor-name 加 anchor() 或 position-area,再配溢出翻转与锚可见性联动。
Web 排版 一行字怎么排布
从字符序列到规整版面的一系列决策:折行、断词、两端对齐、行距、字距调整、竖排转向,均由 CSS Text / Writing Modes 定义。
文字装饰 下划线、着重号与文字特效
下划线远不止 underline:线型 / 粗细 / 颜色 / offset / skip-ink 各自独立;还有中文 text-emphasis 着重号与 text-shadow 等特效。
字体特性 OpenType feature 开关
字体文件内置可由 CSS 启用的排印特性:font-variant-numeric 等宽数字、font-feature-settings 的 OpenType tag、text-autospace。
多行文本展开 / 收起 一行 JS 都不写
「…展开 / 收起」这类交互全用 CSS 做:max-height 截断、float 占位把按钮钉右下角、input:checked 切状态、绝对定位 ::after 靠自身位置判断溢出以自动藏起按钮。
圆角三部曲 从图片滑动门到 corner-shape
border-radius 之前圆角靠切图(SVG 转 PNG + 滑动门 / OOCSS 角对象);border-radius 一行写四角;之后 corner-shape 把圆弧扩展成 squircle / bevel / scoop / notch 的超椭圆家族。
CSS Background 一张 <image> 的 size / position / clip
background 画的是一张 <image>——渐变或 url() 位图——由 size / position / repeat / background-clip 摆布。讲解简写七段、渐变色标硬切换、in oklab 插值色彩空间、radial / linear 几何、灌进字形与 border-area 渐变描边,以及雪碧图如何随 background-size 缩放定位。
CSS 里的 Path 一条路径的四种用途
path() / shape() / <basic-shape> 这类形状值应用于不同属性即呈现不同能力:clip-path 裁剪、shape-outside 环绕、offset-path 轨道、d 改写。
SVG × CSS 可由 CSS 控制的图形文档
SVG 每个图形都是 DOM 节点,可被 CSS 选择器命中、响应 :hover、以 currentColor 着色。讲解嵌入方式矩阵、viewBox 视口映射、attr↔CSS 优先级、fill & stroke、*Units,以及 SVG 当前仍缺失的能力。
CSS Transition 状态间的隐式动画
一组可交互 demo:从 transition 的四个子属性与简写,到可过渡性(离散 vs 插值)、timing-function、@starting-style 入场出场、半路打断的可逆性,以及 transition 与 animation 的取舍。
CSS Animation 能力速览
一组可交互的 CSS 动画演示:animation-* 八个子属性、缓动、scroll-driven、@starting-style、运动路径与 Web Animations API。
iOS 26+ Liquid Glass 验证
MetaColor / FixedWrapper / safe-area 等一组在 iOS 26+ Safari 上的验证 demo,每页带 debug panel;非 iOS 26+ 设备可用 panel 强制开启 spacer 模拟版面。
🌐Web 平台 API15
HTML Parsing 能解析 ≠ 合法
HTML parser 对任意输入都产出确定 DOM、解析过程永不中止;<a> 里套 <a> 能跑,却仍是 non-conforming —— 解析容错与 conformance 是两层。
User-Agent 把 UA 字符串拆开
一条 Mozilla/5.0 (…) Chrome/… Safari/… 里藏着 browser·engine·os·device;用自研 @vega/user-agent 当场拆解,并识别 bot。
HTML 表单 控件 · 提交 · 校验
把 WHATWG「4.10 Forms」规范走一遍:键盘把按键变成字符 → <form> 与提交(form ownership、entry list、三种 enctype、reset 与 dirty value flag)→ 表单控件全家(input 的 22 种 type state、select / datalist、output / progress / meter、fieldset 的 disabled 传播、label)→ 原生控件的边界行为(range 伪元素、RCDATA、maxlength、inputmode、field-sizing)→ 约束校验(ValidityState、校验 API、:user-invalid)与文本选择 API、autocomplete → 实时 masking。每条规范细节都配一个可当场点 / 拖 / 输的原生 demo。
Temporal 新一代日期时间 API
传统 Date 将时刻 / wall-clock 时间 / 时长混杂在单一类型中;Temporal 将其拆分为职责明确、不可变的一组类型。
MessageFormat 2 · Unicode 本地化消息标准
复数、性别、插值、富文本一条消息搞定——Unicode MessageFormat 2.0 (MF2) 的语法、内置函数与 JS API 全覆盖。
Intl 浏览器内置的国际化 API
数字、日期、复数、排序的本地化格式无需手写——浏览器内置的 Intl(ECMA-402)提供完整实现。
glob 路径匹配的迷你语言
**/*.test.ts 这类带星号的路径不是正则,而是为 / 分段路径定制的迷你匹配语言。
URL 一条网址怎么拆开
https://…:8443/p?q#h 由 scheme·host·port·path·query·fragment 拼成;用原生 URL 逐段拆。
Dialog / Popover 原生浮层
弹窗 / 抽屉 / 菜单等浮层可交由原生 top layer、<dialog> 与 Popover API 实现,无需手写遮罩。
Live Photo 把一动一静放上网页
iPhone 的 Live Photo 不是一种文件格式,而是两个文件加一个 asset identifier:一张 HEIC 静图、一段 QuickTime MOV,另有一条 timed metadata track 标出「静图对应哪一帧」。搬上网页要分别回答两件事:这一动一静在格式层怎么配成对(对照 Google Motion Photo 的单文件封装),以及浏览器实际解得开哪一半——本系列实测出的答案与直觉相反。
事件循环 macrotask / microtask / 渲染时机
单线程依靠持续运转的事件循环:取一个 macrotask → 清空 microtask 队列 → 按需渲染 → 取下一个 macrotask。
Passkey / WebAuthn 用密钥替掉密码
passkey 并非更安全的密码,而是更换了认证模型:一对非对称密钥,私钥不出设备、绑定 RP ID、从机制上防御钓鱼。
Signals 响应式内核
Vue ref、Solid createSignal 底层同一套 push-pull 依赖追踪:改一个值,用到它的地方自动更新。
RxJS 响应式流 · 从 Observable 契约到取消竞态
把「随时间陆续到来的多个值」建模成一条可组合、可取消的流:一个十几行就能手写的 Observable 契约,配上 operator,消掉回调地狱与请求竞态。
UX 交互模式 那些有名字的交互细节
Optimistic UI 先更新再请求、Yellow Fade 高亮变化、Snackbar 撤销优先、Safe Triangle / Hover Intent 读懂指针意图、Fitts's Law 点击热区、View Transitions 共享元素转场(含跨文档 MPA)——各自并排对照「有 / 没有」。
🔐系统设计7
CRDT 可变树层级 Replicated Tree
文件树、大纲、图层这类层级数据,多副本离线各改后要无冲突收敛。围绕唯一原语 move(child, parent),讲清并发为何成环、祖先检查如何挡住,以及 undo-do-redo 怎样让任意投递顺序都收敛到同一棵树。
访问控制 / Access Control 从 RBAC 到 policy
权限的两个正交问题——能不能做 (Permission) / 对谁做 (Scope)——从 User→Role→Permission 查表,泛化成判定函数 decide(who, when/where, what, action):RBAC 是 ABAC 的特例,再落到 HTTP / 会员价 / feature flag / 可见性 / Kubernetes 与文件权限等现实 policy;附带列表分页、多租户、role explosion 与变更影响面这些维护期才浮现的账。
DNS 一个名字怎么变成地址
把 mail.vega.dev 变成 IP,靠的是层级委任加缓存。本系列从 zone file 与报文字节讲到 DNSSEC 与「浸透」这个不存在的机制。
OTP / TOTP / HOTP 动态验证码机制
离线生成的 6 位数字为何能与服务器一致?解析 otpauth:// 链接、HOTP(HMAC + 动态截取)、TOTP 以时间片作为 counter。
审批流 Approval Workflow
把「谁、按什么顺序、依据什么规则签字」固化成可配置、可追溯的流程引擎:条件路由、并行会签、决议语义与在途干预,全压在 append-only 的审计红线上。
路由设计 稳定入口与可变目标
路由是一层可控 indirection:对外稳定入口,背后目标随时可换。讲短链 base62、匹配引擎、重定向、deep link、远程配置、客户端路由与 URLPattern。
限流 Rate Limiting 五种放行策略
单位时间内放行多少请求,超出的如何处置。同一串请求喂给五种算法:token bucket 积攒令牌容忍突发、leaky bucket 排队整流输出、固定窗口在两窗交界处放行两倍配额、sliding log 精确却要逐条记戳、sliding counter 用加权近似抹平交界突刺。沿时间轴逐帧推演,末节五者同序列并排对照与选型。
🧪实验5
QQ 风格分组好友列表
两级有序的分组好友列表:分组可重排、可增删改名,好友可在分组间拖动移动。Pointer Events 自绘拖拽(含自动滚动、悬停展开折叠组),扁平数据模型 + 纯函数渲染。
JS Debugger 在线打断点的编辑器
写 JavaScript、点行号设断点,不依赖 DevTools 逐行单步执行——自带一个从零手写的 generator 树遍历解释器。
分支树的网格布局
把一棵「主干 + 分支」的树摊到整数网格上:列号恒等于到根的距离,五种策略各自决定行号,可拖动、可缩放,视口外的节点不进 DOM。
一万条消息的变高虚拟列表
行高事先不知道的虚拟滚动:前缀和加二分定位可见区间,量到真高再改表重算,往头部插入消息时按锚点还原滚动位置。
压缩对比 CompressionStream vs Canvas→PNG
同一份数据分别用原生 CompressionStream 与「字节编码为像素再交给 canvas 编成 PNG」两种方式压缩,往返校验并对比体积。
这个分类暂时没有内容。