一个的 LeetCode 刷题仓库。每道题一个文件,结构固定:
- 题目描述 —— 文件顶部的 TSDoc,写清原题要点与参数含义
- 实现 —— 单一函数,
export default导出,便于测试直接引入 - 思路注释 —— 关键步骤逐行中文注释,说明为什么这样写,而不只是写做了什么
- 结构定义 —— 题目需要的
ListNode/TreeNode就近声明;跨题复用的放在src/data-structure
不追求一行流的最短解,追求半年后回看还能看懂。
| 分类 | 题量 | 分布 |
|---|---|---|
| 二叉树 | 28 | ██████████████████ |
| 动态规划 | 27 | █████████████████ |
| 链表 | 16 | ██████████ |
| 回溯 | 11 | ███████ |
| 数组 | 10 | ██████ |
| 栈与队列 | 10 | ██████ |
| 字符串 | 9 | ██████ |
| 双指针 | 8 | █████ |
| 哈希表 | 6 | ████ |
| 二分查找 | 6 | ████ |
| 排序专题 | 6 | ████ |
| 贪心 | 5 | ███ |
| 前缀和与差分 | 4 | ███ |
| 其他 | 4 | ███ |
下表题量随刷题进度变化,仅作分布快照。
两个归档维度:分类目录按算法归档(一题一类);题库目录按出处归档 (
leetcode-hot-100/剑指 Offer,内部再分二级类)。两者有部分题目重复 —— 同一道题在两处各存一份,方便按不同线索找回。
环境要求:Node ≥ 24、pnpm ≥ 10(见 .node-version 与 package.json#engines)。
pnpm install
pnpm test # 运行全部测试(vitest run)
pnpm test:watch # 监听模式,改完即测调试题解:用 VSCode 打开任意题目文件 → F5 → 选择 node.js 配置。
用的是 Node 原生调试器,不需要 ts-node / tsx 中转,可直接断点
(launch.json 里还保留了 esno、tsx 两种备用配置)。
src/
├── data-structure/ 公共结构:ListNode · TreeNode · DLinkedNode
│
├── 数组/ 链表/ 哈希表/ 字符串/ 双指针/ 栈与队列/ 基础结构
├── 二分查找/ 排序专题/ 前缀和与差分/ 常用技巧
├── 二叉树/ 含 5 个二级类:遍历 / 属性 / 修改与构造 / 二叉搜索树 / 公共祖先
├── 回溯/ 含 3 个二级类:组合 / 排列 / 子集
├── 动态规划/ 含 4 个二级类:0-1 背包 / 完全背包 / 子序列 / 打家劫舍
├── 贪心/ 其他/
│
├── leetcode-hot-100/ 题库维度:热题 100(再分 11 个二级类)
└── 剑指 Offer/ 题库维度:剑指 Offer(再分 12 个二级类)
题目里反复用到的三个节点类,放在 src/data-structure/:
export default class ListNode {
public val: number;
public next: ListNode | null;
constructor(val: number, next: ListNode | null = null) {
this.val = val;
this.next = next;
}
}export default class TreeNode {
public val: number;
public left: TreeNode | null;
public right: TreeNode | null;
constructor(val: number, left: TreeNode | null = null, right: TreeNode | null = null) {
this.val = val;
this.left = left;
this.right = right;
}
}另有 DLinkedNode(带前后指针的双向节点)。题目特有的结构(如带 random 指针的
Node)就近写在题目文件里,避免为一道题污染公共目录。
下面是按分类整理的经典题(题名直达源码文件,短链跳 LeetCode 原题);
src/ 下实际收录的题解更多,这里挑的是最有代表性的那些。
想找别的题,直接浏览对应分类目录即可。
| 题目 | 原题 |
|---|---|
| 202. 快乐数 | happy-number |
| 242. 有效的字母异位词 | valid-anagram |
| 383. 赎金信 | ransom-note |
| 349. 两个数组的交集 | intersection-of-two-arrays |
| 454. 四数相加 II | 4sum-ii |
| 347. 前 K 个高频元素 | top-k-frequent-elements |
| 题目 | 原题 |
|---|---|
| 144. 二叉树的前序遍历 | binary-tree-preorder-traversal |
| 94. 二叉树的中序遍历 | binary-tree-inorder-traversal |
| 145. 二叉树的后序遍历 | binary-tree-postorder-traversal |
| 102. 二叉树的层序遍历 | binary-tree-level-order-traversal |
| 题目 | 原题 |
|---|---|
| 235. 二叉搜索树的最近公共祖先 | lowest-common-ancestor-of-a-binary-search-tree |
| 236. 二叉树的最近公共祖先 | lowest-common-ancestor-of-a-binary-tree |
| 题目 | 原题 |
|---|---|
| 416. 分割等和子集 | partition-equal-subset-sum |
| 题目 | 原题 |
|---|---|
| 322. 零钱兑换 | coin-change |
| 139. 单词拆分 | word-break |
| 279. 完全平方数 | perfect-squares |
用 Vitest(globals 模式,配置见 vitest.config.ts),
测试文件按目录就近放在 __test__/ 下,目前覆盖:
二分查找 · 数组 · 字符串 · 哈希表 · 栈与队列 · 栈与队列/单调栈 ·
排序专题 · 动态规划/完全背包 · 动态规划/打家劫舍 · leetcode-hot-100/滑动窗口
新增测试:在题目所在目录建 __test__/basic.test.ts 即可(include 已限定
src/**/*.{test,spec}.{ts,tsx})。
测试是逐步补上的 —— 早期题目只有实现与注释,覆盖率仍在提升。
| 项 | 约定 |
|---|---|
| 文件命名 | <题号>. <题名>.ts;无题号的算法(排序专题)直接以算法名命名 |
| 导出方式 | 每题 export default 主函数 |
| 结构定义 | 题目专有的就近声明;跨题复用的放 src/data-structure/ |
| 代码风格 | Prettier 统一:120 列 / 4 空格 / 双引号 / 分号,保存自动格式化 |
| TS 配置 | strict: true,但 strictNullChecks: false —— 刷题时少一些空值噪音 |
| 题库 | 题量 | 二级分类 |
|---|---|---|
| leetcode-hot-100 | 45 | (根目录题目) 16 · 二叉树 2 · 前缀和 2 · 双指针 4 · 哈希 3 · 字符串 1 · 技巧 5 · 数组 2 · 栈 1 · 滑动窗口 3 · 矩阵 3 · 链表 3 |
| 剑指 Offer | 56 | (根目录题目) 15 · 位运算 3 · 分治算法 2 · 动态规划 5 · 双指针 7 · 字符串 4 · 排序 2 · 搜索与回溯算法 2 · 数学 3 · 查找算法 6 · 栈与队列 4 · 链表 3 |
- 仓库持续更新:新题按分类归档;来自题库的题目会同时进两个维度
- 除题解外,
排序专题/收录了基础排序的手写实现(冒泡 / 选择 / 插入 / 希尔 / 归并 / 快速),堆排序、基数排序等仍在待办中 - 如果你也在刷同一道题:欢迎参考,但先自己写一遍再看 —— 题解的价值在于思路,不在答案