CC 咖啡猫的工作空间 Coding Space

算法解题框架与 LeetCode 刷题清单

题目来源:labuladong 算法笔记官方习题章节。本文记录整理时的 26 个专题、171 道主习题;官网调整后数量可能变化。标记说明:📋 = 官网习题章节收录,⭐ = 官网文章引用或推荐补充。


速成学习路线(来自官网)

第0步:先刷二叉树(建立递归思维) → 第1章:基本技巧 → 第2章:二叉树进阶 → 第3章:动态规划 → 第4章:其他算法

怎样把清单变成能力

清单解决“练什么”,不能证明“已经掌握”。每个专题按下面的闭环推进:

  1. 先选一道代表题,不看答案写出输入、输出、约束和最小反例。
  2. 用一句话定义状态或指针含义,再写代码;不能解释变量含义时,模板还没有真正掌握。
  3. 用示例、边界和随机小数据验证,并记录时间、空间复杂度。
  4. 隔 1 天和 1 周各重写一次;第二次仍需要背完整代码时,回到框架与不变量。
记录项 示例
题目与日期 209. 长度最小的子数组,2026-09-06
识别信号 连续子数组、元素非负、窗口和达到阈值
不变量 收缩前窗口满足条件;收缩后继续寻找更短答案
失败用例 空数组、单元素、目标不可达、答案在数组末尾
复杂度 时间 O(n),空间 O(1)
复习结果 次日独立完成;一周后边界条件出错

可先读 数据结构 建立术语,再用 算法套路与解题框架 理解模板来源,最后在本页选题验证。


第一章:基本技巧

1.1 链表双指针

📋 官网习题章节:链表双指针经典习题

核心框架

虚拟头结点 → 简化边界处理
快慢指针(速度差)→ 中点、环检测
前后指针(步数差)→ 倒数第K个
双指针分别构建 → 链表分解
优先级队列 → K路合并

官网习题(6道)

# 题目 核心技巧
82 删除排序链表中的重复元素 II 链表分解(双指针分别构建)
378 有序矩阵中第 K 小的元素 优先级队列 / 二分
373 查找和最小的 K 对数字 优先级队列
2 两数相加 同步双指针 + 进位
445 两数相加 II 栈辅助 / 反转链表
287 寻找重复数 快慢指针(等价环形链表II)

⭐ 文章中引用:83(删除排序链表中的重复元素)、23(合并K个升序链表)、142(环形链表 II)


1.2 数组双指针

📋 官网习题章节:数组双指针经典习题

核心框架

快慢指针(同向) → 原地去重、删除元素、移动零
左右指针(相向) → 两数之和II、反转数组
矩阵遍历技巧 → 转置、对角线、旋转

官网习题(9道)

# 题目 核心技巧
80 删除有序数组中的重复项 II 快慢指针变体
125 验证回文串 左右指针
75 颜色分类 三指针(荷兰国旗)
88 合并两个有序数组 逆向双指针
977 有序数组的平方 左右指针
1329 将矩阵按对角线排序 矩阵对角线遍历
1260 二维网格迁移 一维化索引
867 转置矩阵 矩阵操作
14 最长公共前缀 纵向扫描

⭐ 文章中引用:26(删除有序数组中的重复项)、27(移除元素)、283(移动零)、21(合并两个有序链表)、151(颠倒字符串中的单词)


1.3 滑动窗口

📋 官网习题章节:滑动窗口算法经典习题

核心框架

int left = 0, right = 0;
while (right < nums.length) {
    // 扩大窗口,加入 nums[right]
    right++;
    while (需要收缩) {
        // 缩小窗口,移除 nums[left]
        left++;
    }
    // 更新答案
}

官网习题(7道)

# 题目 特征
1658 将 x 减到 0 的最小操作数 逆向思维:找最长子数组和为 sum-x
1004 最大连续1的个数 III 条件窗口(最多K个0)
424 替换后的最长重复字符 窗口内最多K个不同字符
219 存在重复元素 II 固定窗口 + HashSet
220 存在重复元素 III 桶排序 / TreeSet
209 长度最小的子数组 收缩条件:sum >= target
395 至少有 K 个重复字符的最长子串 分治 + 滑动窗口

⭐ 文章中引用:713(乘积小于K的子数组)、560(和为K的子数组)、1425(带限制的子序列和)、862(和至少为K的最短子数组)、53(最大子数组和)


1.4 二分搜索

📋 官网习题章节:二分搜索算法经典习题

核心框架

基础框架:两端都闭 [left, right],while (left <= right)
左侧边界:mid == target → right = mid - 1,返回 left
右侧边界:mid == target → left = mid + 1,返回 right
泛化运用:f(x) 单调 + 求边界值 → 二分搜索

官网习题(11道)

# 题目 核心技巧
566 重塑矩阵 一维化索引
74 搜索二维矩阵 二维 → 一维二分
240 搜索二维矩阵 II 右上角开始搜索 / 二分
392 判断子序列 双指针 / 二分预处理
658 找到 K 个最接近的元素 二分 + 双指针扩展
35 搜索插入位置 左侧边界变体
162 寻找峰值 二分爬坡法
852 山脉数组的峰顶索引 二分找最大值
33 搜索旋转排序数组 二分 + 分段判断
81 搜索旋转排序数组 II 含重复元素处理
153 寻找旋转排序数组中的最小值 二分旋转点

⭐ 文章中引用:792(匹配子序列的单词数)、5(最长回文子串)


1.5 栈

📋 官网习题章节:栈的经典习题

官网习题(9道)

# 题目 核心技巧
71 简化路径 栈处理路径
143 重排链表 栈辅助(后进先出)
20 有效的括号 栈匹配括号
150 逆波兰表达式求值 栈计算
225 用队列实现栈 数据结构设计
388 文件的最长绝对路径 栈记录层级
394 字符串解码 栈 + 递归
155 最小栈 辅助栈存最小值
895 最大频率栈 频率Map + 栈Map

⭐ 文章中引用:239(滑动窗口最大值)


1.6 队列

📋 官网习题章节:队列的经典习题

官网习题(5道)

# 题目 核心技巧
933 最近的请求次数 队列维护时间窗口
622 设计循环队列 数组实现循环队列
641 设计循环双端队列 双向操作
1670 设计前中后队列 双端队列设计
2073 买票需要的时间 队列模拟

⭐ 文章中引用:346(数据流中的移动平均值)


1.7 单调栈

📋 官网习题章节:单调栈的几种变体及经典习题

核心框架

单调栈模板:倒序遍历 + while 弹出较小元素
  while (!stack.isEmpty() && stack.peek() <= nums[i]) stack.pop();
  res[i] = stack.isEmpty() ? 0 : stack.peek();
  stack.push(nums[i]);
适用场景:下一个更大/更小元素、柱状图最大矩形

官网习题(8道)

# 题目 核心技巧
1019 链表中的下一个更大节点 单调栈 + 链表
1944 队列中可以看到的人数 单调栈(递减栈)
1475 商品折扣后的最终价格 单调栈(正序遍历)
901 股票价格跨度 单调栈(存跨度)
402 移掉 K 位数字 单调栈 + 贪心
853 车队 到达时间 + 单调栈
581 最短无序连续子数组 单调栈找左右边界
84 柱状图中最大的矩形 单调栈经典题

第二章:二叉树

二叉树思维模式

遍历思维(traverse):无返回值 + 外部变量
  前序位置:刚进入节点 → 自上而下传参
  中序位置:左子树处理完 → BST有序
  后序位置:即将离开节点 → 可获得子树信息(能力最强)

分解问题思维(f(root) 有返回值):
  定义递归函数 → 子树答案推导 → 后序位置写逻辑

层序遍历:BFS + Queue + for (int i = 0; i < sz; i++) 按层处理

2.1 用「遍历」思维解题 I

📋 官网习题章节:用「遍历」思维解题 I

官网习题(6道)

# 题目 核心技巧
257 二叉树的所有路径 前序遍历 + 回溯
129 求根节点到叶节点数字之和 前序遍历传参
199 二叉树的右视图 DFS记录每层第一个
988 从叶结点开始的最小字符串 前序遍历 + 回溯比较
1022 从根到叶的二进制数之和 前序遍历传参
1457 二叉树中的伪回文路径 前序遍历 + 位运算

2.2 用「遍历」思维解题 II

📋 官网习题章节:用「遍历」思维解题 II

官网习题(7道)

# 题目 核心技巧
404 左叶子之和 遍历 + 条件判断
623 在二叉树中增加一行 遍历 + 层数判断
971 翻转二叉树以匹配先序遍历 遍历 + 贪心翻转
987 二叉树的垂序遍历 遍历 + 坐标排序
993 二叉树的堂兄弟节点 遍历记录父节点和深度
1315 祖父节点值为偶数的节点和 遍历传参爷爷值
1448 统计二叉树中好节点的数目 遍历传参路径最大值

2.3 用「分解问题」思维解题 I

📋 官网习题章节:用「分解问题」思维解题 I

官网习题(7道)

# 题目 核心技巧
105 从前序与中序遍历序列构造二叉树 找根 + 递归构建左右子树
106 从中序与后序遍历序列构造二叉树 找根 + 递归构建左右子树
889 根据前序和后序遍历构造二叉树 左子树根确定分界
331 验证二叉树的前序序列化 节点和空位的关系
894 所有可能的真二叉树 枚举左子树 + 右子树组合
998 最大二叉树 II 插入节点保持最大树
1110 删点成林 后序分解 + 处理删除

⭐ 文章中引用:654(最大二叉树)


2.4 用「分解问题」思维解题 II

📋 官网习题章节:用「分解问题」思维解题 II

官网习题(4道)

# 题目 核心技巧
100 相同的树 分解:左右都相同
101 对称二叉树 分解:左的左 = 右的右
951 翻转等价二叉树 分解:两种情况之一成立
124 二叉树中的最大路径和 后序分解(单边 vs 双边)

⭐ 文章中引用:543(二叉树的直径)、366(寻找二叉树的叶子节点)


2.5 运用层序遍历解题 I

📋 官网习题章节:运用层序遍历解题 I

官网习题(11道)

# 题目 核心技巧
102 二叉树的层序遍历 BFS 队列模板
107 二叉树的层序遍历 II 层序遍历 + 结果反转
103 二叉树的锯齿形层序遍历 BFS + 方向标记
117 填充每个节点的下一个右侧节点指针 II BFS 连接同层节点
662 二叉树最大宽度 BFS + 节点编号
515 在每个树行中找最大值 BFS 每层统计
637 二叉树的层平均值 BFS 每层统计
958 二叉树的完全性检验 BFS + 空节点标记
1161 最大层内元素和 BFS 每层求和
1302 层数最深叶子节点的和 BFS 求最后一层和
1609 奇偶树 BFS + 层条件判断

⭐ 文章中引用:116(填充每个节点的下一个右侧节点指针)、1104(二叉树寻路)、199(二叉树的右视图)


2.6 运用层序遍历解题 II

📋 官网习题章节:运用层序遍历解题 II

官网习题(3道)

# 题目 核心技巧
919 完全二叉树插入器 队列维护插入位置
872 叶子相似的树 层序遍历收集叶节点
863 二叉树中所有距离为 K 的结点 BFS + 父节点映射

第三章:动态规划

DP 核心框架

三步法:
1. 明确状态(会变化的变量有哪些)
2. 明确选择(导致状态变化的行为)
3. 定义 dp 数组/函数

自顶向下:递归 + 备忘录
自底向上:迭代 + DP table

子序列问题 → dp[i] = 以 i 结尾的结果
双字符串 → dp[i][j] = s1[0..i] 和 s2[0..j] 的关系

3.1 动态规划经典习题 I

📋 官网习题章节:动态规划经典习题 I

官网习题(6道)

# 题目 核心技巧
343 整数拆分 dp[n] = max(j × (n-j), j × dp[n-j])
63 不同路径 II 网格DP + 障碍物处理
1262 可被三整除的最大和 DP + 余数状态
120 三角形最小路径和 自底向上 DP
368 最大整除子集 DP + 记录前驱
718 最长重复子数组 dp[i][j] 双序列 DP

3.2 动态规划经典习题 II

📋 官网习题章节:动态规划经典习题 II

官网习题(5道)

# 题目 核心技巧
97 交错字符串 双序列 DP
152 乘积最大子数组 同时维护 min 和 max
221 最大正方形 dp[i][j] = min(上,左,左上) + 1
329 矩阵中的最长递增路径 记忆化搜索(DFS + 备忘录)
1235 规划兼职工作 按结束时间排序 + DP + 二分

⭐ 文章中引用:21(合并两个有序链表)、53(最大子数组和)


3.3 背包问题经典习题

📋 官网习题章节:背包问题经典习题

核心框架

0-1背包(每个物品选或不选):
  二维:dp[i][w] = max(dp[i-1][w], dp[i-1][w-wt[i]] + val[i])
  一维优化:for w = W..0(逆向遍历,保证不重复)

完全背包(每个物品可选无限次):
  一维:for w = 0..W(正向遍历,允许重复选)

子集背包(能否装满):
  dp[i][w] = dp[i-1][w] || dp[i-1][w-nums[i]](布尔DP)

官网习题(3道)

# 题目 类型
1049 最后一块石头的重量 II 0-1背包(子集背包变体)
474 一和零 二维费用的0-1背包
3180 执行操作可获得的最大总奖励 I 0-1背包变体

第四章:其他经典算法

4.1 回溯算法经典习题 I

📋 官网习题章节:回溯算法经典习题 I

核心框架

result = []
void backtrack(路径, 选择列表):
    if 满足结束条件: result.add(路径); return
    for 选择 in 选择列表:
        做选择 → backtrack → 撤销选择

子集/组合 → 用 start(防止回头)
排列 → 用 used[](标记已选)
有重复元素 → 先排序 + 同层剪枝

官网习题(10道)

# 题目 特征
967 连续差相同的数字 回溯构造数字
980 不同路径 III 回溯遍历所有路径
526 优美的排列 回溯 + 约束
491 非递减子序列 回溯 + 同层去重
131 分割回文串 回溯 + 预处理
93 复原 IP 地址 回溯 + 剪枝
89 格雷编码 回溯 / 公式法
17 电话号码的字母组合 回溯组合
79 单词搜索 二维回溯
473 火柴拼正方形 回溯 + 剪枝(桶视角)

⭐ 文章中引用:40(组合总和 II)


4.2 回溯算法经典习题 II

📋 官网习题章节:回溯算法经典习题 II

官网习题(7道)

# 题目 特征
1219 黄金矿工 二维回溯 + 最大值
1849 将字符串拆分为递减的连续值 回溯 + 数值比较
1593 拆分字符串使唯一子字符串数目最大 回溯 + 去重
1079 活字印刷 回溯排列(含重复)
996 平方数组的数目 回溯排列 + 约束
784 字母大小写全排列 回溯 + 大小写变换
638 大礼包 回溯 + DP

4.3 回溯算法经典习题 III

📋 官网习题章节:回溯算法经典习题 III

官网习题(4道)

# 题目 特征
301 删除无效的括号 回溯 + 最少删除
2850 将石头分散到网格图的最少移动次数 回溯 + 全排列匹配
1723 完成所有工作的最短时间 回溯 + 任务分配
2305 公平分发饼干 回溯 + 桶分配

⭐ 文章中引用:1011(在D天内送达包裹的能力)


4.4 BFS 经典习题 I

📋 官网习题章节:BFS 经典习题 I

核心框架

int bfs(start, target) {
    Queue q; q.offer(start); visited.add(start);
    int step = 0;
    while (!q.isEmpty()) {
        int sz = q.size();
        for (int i = 0; i < sz; i++) {
            cur = q.poll();
            if (cur == target) return step;
            for (neighbor : cur.neighbors)
                if (!visited.contains(n)) { q.offer(n); visited.add(n); }
        }
        step++;
    }
}

官网习题(10道)

# 题目 核心技巧
919 完全二叉树插入器 BFS 维护插入位置
117 填充每个节点的下一个右侧节点指针 II BFS 连接同层节点
662 二叉树最大宽度 BFS + 节点编号
863 二叉树中所有距离为 K 的结点 BFS + 父节点映射
310 最小高度树 BFS 拓扑排序(剥洋葱)
841 钥匙和房间 BFS / DFS 连通性
1306 跳跃游戏 III BFS 跳跃搜索
433 最小基因变化 BFS + 字符变换
1926 迷宫中离入口最近的出口 矩阵 BFS
1091 二进制矩阵中的最短路径 矩阵 BFS

⭐ 文章中引用:102(二叉树的层序遍历)、116(填充每个节点的下一个右侧节点指针)、1104(二叉树寻路)、199(二叉树的右视图)、286(墙与门)


4.5 BFS 经典习题 II

📋 官网习题章节:BFS 经典习题 II

官网习题(10道)

# 题目 核心技巧
994 腐烂的橘子 多源 BFS
924 尽量减少恶意软件的传播 BFS + 连通分量
2101 引爆最多的炸弹 BFS 有向图传播
542 01 矩阵 多源 BFS
417 太平洋大西洋水流问题 DFS/BFS + 逆流
365 水壶问题 BFS 状态搜索 / 数学
721 账户合并 BFS/并查集合并连通分量
2850 将石头分散到网格图的最少移动次数 BFS 最短路
127 单词接龙 BFS + 双向BFS
399 除法求值 BFS 图搜索

⭐ 文章中引用:111(二叉树的最小深度)、1091(二进制矩阵中的最短路径)


4.6 Dijkstra 算法经典习题

📋 官网习题章节:Dijkstra 算法经典习题

核心框架

// Dijkstra: 优先队列 + distTo数组 + 松弛操作
PriorityQueue<State> pq; // 按distFromStart排序
int[] distTo = new int[n]; Arrays.fill(distTo, INF);
distTo[start] = 0; pq.offer(new State(start, 0));
while (!pq.isEmpty()) {
    State cur = pq.poll();
    if (cur.distFromStart > distTo[cur.id]) continue; // 跳过旧数据
    for (neighbor : neighbors) {
        int newDist = distTo[cur.id] + weight;
        if (newDist < distTo[neighbor]) {
            distTo[neighbor] = newDist;
            pq.offer(new State(neighbor, newDist));
        }
    }
}

官网习题(5道)

# 题目 核心技巧
743 网络延迟时间 Dijkstra 模板题
1631 最小体力消耗路径 Dijkstra 变体(最小化路径最大值)
1514 概率最大的路径 Dijkstra 变体(最大化路径积)
1368 使网格图至少有一条有效路径的最小代价 Dijkstra + 0-1 BFS
787 K 站中转内最便宜的航班 Dijkstra + 中转次数限制

4.7 并查集(Union-Find)经典习题

📋 官网习题章节:并查集经典习题

核心框架

class UF {
    int[] parent; int count;
    int find(int x) { // 路径压缩
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }
    void union(int p, int q) {
        int rootP = find(p), rootQ = find(q);
        if (rootP == rootQ) return;
        parent[rootQ] = rootP; count--;
    }
}

官网习题(3道)

# 题目 核心技巧
547 省份数量 并查集模板题
1361 验证二叉树 并查集检查连通性
947 移除最多的同行或同列石头 并查集合并行和列

⭐ 文章中引用:261(以图判树)


4.8 线段树经典习题

📋 官网习题章节:线段树经典习题

官网习题(4道)

# 题目 核心技巧
729 我的日程安排表 I 线段树 / TreeSet 区间
731 我的日程安排表 II 线段树 + 双重预订
732 我的日程安排表 III 线段树 + 最大预订次数
699 掉落的方块 线段树(区间更新+最大值查询)

4.9 Trie 树算法习题

📋 官网习题章节:Trie 树算法习题

核心框架

class TrieNode {
    TrieNode[] children = new TrieNode[26];
    boolean isEnd = false;
}
class Trie {
    void insert(String word) { /* 遍历字符,创建节点 */ }
    boolean search(String word) { /* 精确匹配 */ }
    boolean startsWith(String prefix) { /* 前缀匹配 */ }
}

官网习题(4道)

# 题目 核心技巧
208 实现 Trie (前缀树) Trie 模板题
648 单词替换 Trie 找最短前缀
211 添加与搜索单词 - 数据结构设计 Trie + 通配符 DFS
677 键值映射 Trie 节点存值

4.10 数据结构设计

📋 官网习题章节:更多经典设计习题

官网习题(7道)

# 题目 核心技巧
729 我的日程安排表 I 有序集合 / 线段树
950 按递增顺序显示卡牌 队列模拟
1700 无法吃午餐的学生数量 队列 + 计数
155 最小栈 辅助栈存最小值
1670 设计前中后队列 双端队列设计
895 最大频率栈 频率Map + 栈Map
284 窥视迭代器 缓存下一个元素

⭐ 文章中引用:239(滑动窗口最大值)、251(展开二维向量)


附录

一、排序算法速查表

算法 时间(平均) 时间(最坏) 空间 稳定
快速排序 O(n log n) O(n²) O(log n)
归并排序 O(n log n) O(n log n) O(n)
堆排序 O(n log n) O(n log n) O(1)
插入排序 O(n²) O(n²) O(1)
冒泡排序 O(n²) O(n²) O(1)
选择排序 O(n²) O(n²) O(1)
计数排序 O(n+k) O(n+k) O(k)
基数排序 O(nk) O(nk) O(n+k)
桶排序 O(n+k) O(n²) O(n+k)

二、习题章节汇总

章节 专题 题目数
1.1 链表双指针 6
1.2 数组双指针 9
1.3 滑动窗口 7
1.4 二分搜索 11
1.5 9
1.6 队列 5
1.7 单调栈 8
2.1~2.2 二叉树遍历思维 13
2.3~2.4 二叉树分解思维 11
2.5~2.6 二叉树层序遍历 14
3.1~3.2 动态规划 11
3.3 背包问题 3
4.1~4.3 回溯算法 21
4.4~4.5 BFS 算法 20
4.6 Dijkstra 5
4.7 并查集 3
4.8 线段树 4
4.9 Trie 树 4
4.10 数据结构设计 7
合计 26个专题 171

三、使用建议

  1. 按依赖选择顺序:递归不熟时先练二叉树;数组和链表基础薄弱时先回到基本技巧,不必机械遵循完整目录。
  2. 先写不变量再写模板:模板只是实现骨架,题目约束决定窗口何时收缩、状态如何转移、节点是否可重复访问。
  3. 一题多解用于比较边界:记录不同解法需要的前提、复杂度和失败用例,而不只是多抄一份代码。
  4. 限时服务于诊断:时间到了先标记卡在建模、边界还是编码,再查看提示;固定分钟数不是能力标准。
  5. 用间隔复习检验迁移:复习时更换输入或相邻题,确认能从特征推出框架,而不是记住题号。

四、专题完成标准

  • 能说明这个框架解决什么问题,以及至少一个不适用场景。
  • 能从空输入、最小输入、重复值、极值和无解情况中选择相关边界。
  • 代码有可运行入口或在线判题记录,示例输出与预期一致。
  • 能解释时间与空间复杂度来自哪一层循环、递归树或数据结构操作。
  • 一周后能独立完成一道同类变体,并说出它与原题的关键差异。

本页是选题索引,不替代题目原文、约束和独立验证。题目编号、难度与官方专题可能调整,练习时以题目当前描述为准。

📋 = 官网习题章节收录(171道) ⭐ = 官网文章引用/推荐补充 🟢 简单 🟡 中等 🔴 困难