本周总览
7 天 / 7 个高频模板每日安排
每天 3 道必刷 + 晚间复习
Day 1
数组快慢指针
模板:原地修改数组 / 删除元素 / 保持相对顺序
识别信号
- 原地修改
- 返回新长度
- 删除某元素
- 把满足条件的元素放前面
必刷题
- 27. 移除元素
- 26. 删除有序数组中的重复项
- 283. 移动零
可选题
- 80. 删除有序数组中的重复项 II
- 905. 按奇偶排序数组
晚上:重做最卡的一题,默写快慢指针模板,总结“fast 读 / slow 写”。
Day 2
哈希表
模板:set / map 判重、计数、配对
识别信号
- 是否存在
- 查找配对
- 统计频率
- 找重复元素
必刷题
- 1. 两数之和
- 242. 有效的字母异位词
- 217. 存在重复元素
可选题
- 202. 快乐数
- 49. 字母异位词分组
晚上:默写 set 判重模板和 map 计数模板,区分“有没有”和“出现几次”。
Day 3
链表基础
模板:dummy 节点 / 遍历 / 指针修改
识别信号
- 删除链表节点
- 头节点边界处理
- 反转链表
- 合并链表
必刷题
- 206. 反转链表
- 21. 合并两个有序链表
- 83. 删除排序链表中的重复元素
可选题
- 203. 移除链表元素
- 24. 两两交换链表中的节点
晚上:不看答案手写反转链表,先画图再改指针。
Day 4
快慢指针
模板:找中点 / 判断有环 / 找倒数第 N 个
识别信号
- 中间节点
- 环
- 倒数第 N 个
- 一次遍历解决
必刷题
- 876. 链表的中间结点
- 141. 环形链表
- 19. 删除链表的倒数第 N 个结点
可选题
- 234. 回文链表
- 142. 环形链表 II
晚上:复盘边界条件,默写找中点与找倒数节点的写法。
Day 5
栈
模板:括号匹配 / 最近相关元素 / 后进先出
识别信号
- 括号匹配
- 配对合法性
- 后进先出
- 最近一个未处理元素
必刷题
- 20. 有效括号
- 155. 最小栈
- 232. 用栈实现队列
可选题
- 150. 逆波兰表达式求值
- 394. 字符串解码
晚上:重写有效括号,说明为什么括号题天然适合栈。
Day 6
二分查找
模板:标准二分 / 左右边界 / 有序查找
识别信号
- 有序数组
- O(log n)
- 第一个 / 最后一个满足条件的位置
- 单调性
必刷题
- 704. 二分查找
- 35. 搜索插入位置
- 34. 在排序数组中查找元素的第一个和最后一个位置
可选题
- 33. 搜索旋转排序数组
- 162. 寻找峰值
晚上:默写标准二分模板,重点检查 left/right/mid 和边界收缩。
Day 7
滑动窗口
模板:连续区间 / 动态维护状态 / 最长最短子串子数组
识别信号
- 连续子串 / 子数组
- 最长 / 最短
- 满足某种条件
- 窗口右扩左缩
必刷题
- 209. 长度最小的子数组
- 3. 无重复字符的最长子串
- 438. 找到字符串中所有字母异位词
可选题
- 567. 字符串的排列
- 76. 最小覆盖子串
晚上:总结窗口什么时候扩、什么时候缩、窗口里维护什么状态。
Day 1 详解:数组快慢指针
可扩展内容样板这一类题到底在做什么
本质是在 一次遍历 里,把“该保留的数据”稳定地写回数组前部。fast 负责扫描原数组,slow 负责写入下一个有效位置。
- fast:一直往前读,遍历每个元素
- slow:只在遇到有效元素时写入并前进
- 返回值:通常返回新数组长度
slow
通用识别口诀
- 看到“原地修改数组” → 先想快慢指针
- 看到“删除某元素但不能开新数组” → fast 读、slow 写
- 看到“去重 / 压缩 / 移零 / 保序” → 快慢指针高频出现
- 看到“返回新长度” → slow 大概率就是答案
JS 通用模板
function compactArray(nums, isValid) {
let slow = 0;
for (let fast = 0; fast < nums.length; fast++) {
if (isValid(nums[fast], fast, nums)) {
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
适用:移除元素、保留满足条件的值、把有效元素收紧到前面。
LeetCode 27:移除元素
function removeElement(nums, val) {
let slow = 0;
for (let fast = 0; fast < nums.length; fast++) {
if (nums[fast] !== val) {
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
LeetCode 26:删除有序数组中的重复项
function removeDuplicates(nums) {
if (nums.length === 0) return 0;
let slow = 1;
for (let fast = 1; fast < nums.length; fast++) {
if (nums[fast] !== nums[fast - 1]) {
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
LeetCode 283:移动零
function moveZeroes(nums) {
let slow = 0;
for (let fast = 0; fast < nums.length; fast++) {
if (nums[fast] !== 0) {
[nums[slow], nums[fast]] = [nums[fast], nums[slow]];
slow++;
}
}
}
刷题思路模板
- 先问:这题是不是要求 原地 处理?
- 再问:哪些元素应该被保留?
- 让
fast扫完整个数组 - 当元素应该保留时,写到
slow位置 - 最后返回
slow,或者把slow前面的结果作为有效区间
常见坑点
- 把
slow当成“当前元素下标”而不是“下一个写入位置” - 忘了题目要求是“原地修改”
- 26 题里去重时,比较对象写错了
- 283 题写完非零元素后,忘记处理后面的零,或者交换逻辑写乱
- 返回数组而不是返回新长度
今天建议你这样练
- 先背下来一句话:fast 读,slow 写
- 直接做 27,理解最基础模板
- 再做 26,体会“有序数组 + 去重”的变种
- 最后做 283,体会“保序 + 原地交换”
- 晚上不看答案,手写这 3 题的核心循环
后续内容如何设计优化
建议的数据结构每个 Day 固定 6 个模块
- 模板定义:这类题在解决什么问题
- 识别信号:看到什么题意想到这个模板
- 通用代码模板:JS / 以后也可加 Python
- 例题拆解:1~3 道经典题的解法思路
- 坑点清单:边界、返回值、指针更新顺序
- 复习提示:晚上默写什么、复盘什么
建议的页面形态
- 顶部保留周视图,方便总览
- 每个 Day 增加“展开详解”区块
- 代码块统一支持复制按钮(下一版可加 JS)
- 每道题都能挂“我的思路 / 易错点 / 一句话总结”
- 后面可加入本地打卡状态和已完成标记
最适合你的迭代顺序
- 先把 Day 1 ~ Day 7 全部补成这种详解版
- 再给每道题加题解思路
- 再补 JS 模板库总页
- 最后加本地打卡、折叠、筛选和搜索
每日执行方式
复健核心:模板驱动白天
- 先看模板 10~15 分钟
- 搞清适用场景、识别信号、核心框架、易错点
- 刷 3 道必刷题
- 有余力再做 1~2 道可选题
晚上
- 重做当天最卡的 1~2 道题
- 不看答案默写模板
- 写一句总结:看到什么信号就该想到这个模板
最低完成标准
- 每天 3 道必刷题
- 每天复习 1 道错题
- 每天默写 1 个模板
- 一周完成 21 道核心题
本周核心题单
21 道- 27. 移除元素
- 26. 删除有序数组中的重复项
- 283. 移动零
- 1. 两数之和
- 242. 有效的字母异位词
- 217. 存在重复元素
- 206. 反转链表
- 21. 合并两个有序链表
- 83. 删除排序链表中的重复元素
- 876. 链表的中间结点
- 141. 环形链表
- 19. 删除链表的倒数第 N 个结点
- 20. 有效括号
- 155. 最小栈
- 232. 用栈实现队列
- 704. 二分查找
- 35. 搜索插入位置
- 34. 在排序数组中查找元素的第一个和最后一个位置
- 209. 长度最小的子数组
- 3. 无重复字符的最长子串
- 438. 找到字符串中所有字母异位词