DSA Interview Rehab

算法模板学习计划

按模板学习、按题型刷题、晚上复习默写。先把手感找回来,再逐步扩展到更多题型。

本周总览

7 天 / 7 个高频模板
Day 1数组快慢指针
Day 2哈希表
Day 3链表基础
Day 4快慢指针
Day 5
Day 6二分查找
Day 7滑动窗口

每日安排

每天 3 道必刷 + 晚间复习
Day 1

数组快慢指针

模板:原地修改数组 / 删除元素 / 保持相对顺序

识别信号

  • 原地修改
  • 返回新长度
  • 删除某元素
  • 把满足条件的元素放前面

必刷题

  1. 27. 移除元素
  2. 26. 删除有序数组中的重复项
  3. 283. 移动零

可选题

  • 80. 删除有序数组中的重复项 II
  • 905. 按奇偶排序数组
晚上:重做最卡的一题,默写快慢指针模板,总结“fast 读 / slow 写”。
Day 2

哈希表

模板:set / map 判重、计数、配对

识别信号

  • 是否存在
  • 查找配对
  • 统计频率
  • 找重复元素

必刷题

  1. 1. 两数之和
  2. 242. 有效的字母异位词
  3. 217. 存在重复元素

可选题

  • 202. 快乐数
  • 49. 字母异位词分组
晚上:默写 set 判重模板和 map 计数模板,区分“有没有”和“出现几次”。
Day 3

链表基础

模板:dummy 节点 / 遍历 / 指针修改

识别信号

  • 删除链表节点
  • 头节点边界处理
  • 反转链表
  • 合并链表

必刷题

  1. 206. 反转链表
  2. 21. 合并两个有序链表
  3. 83. 删除排序链表中的重复元素

可选题

  • 203. 移除链表元素
  • 24. 两两交换链表中的节点
晚上:不看答案手写反转链表,先画图再改指针。
Day 4

快慢指针

模板:找中点 / 判断有环 / 找倒数第 N 个

识别信号

  • 中间节点
  • 倒数第 N 个
  • 一次遍历解决

必刷题

  1. 876. 链表的中间结点
  2. 141. 环形链表
  3. 19. 删除链表的倒数第 N 个结点

可选题

  • 234. 回文链表
  • 142. 环形链表 II
晚上:复盘边界条件,默写找中点与找倒数节点的写法。
Day 5

模板:括号匹配 / 最近相关元素 / 后进先出

识别信号

  • 括号匹配
  • 配对合法性
  • 后进先出
  • 最近一个未处理元素

必刷题

  1. 20. 有效括号
  2. 155. 最小栈
  3. 232. 用栈实现队列

可选题

  • 150. 逆波兰表达式求值
  • 394. 字符串解码
晚上:重写有效括号,说明为什么括号题天然适合栈。
Day 6

二分查找

模板:标准二分 / 左右边界 / 有序查找

识别信号

  • 有序数组
  • O(log n)
  • 第一个 / 最后一个满足条件的位置
  • 单调性

必刷题

  1. 704. 二分查找
  2. 35. 搜索插入位置
  3. 34. 在排序数组中查找元素的第一个和最后一个位置

可选题

  • 33. 搜索旋转排序数组
  • 162. 寻找峰值
晚上:默写标准二分模板,重点检查 left/right/mid 和边界收缩。
Day 7

滑动窗口

模板:连续区间 / 动态维护状态 / 最长最短子串子数组

识别信号

  • 连续子串 / 子数组
  • 最长 / 最短
  • 满足某种条件
  • 窗口右扩左缩

必刷题

  1. 209. 长度最小的子数组
  2. 3. 无重复字符的最长子串
  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++;
    }
  }
}

刷题思路模板

  1. 先问:这题是不是要求 原地 处理?
  2. 再问:哪些元素应该被保留?
  3. fast 扫完整个数组
  4. 当元素应该保留时,写到 slow 位置
  5. 最后返回 slow,或者把 slow 前面的结果作为有效区间

常见坑点

  • slow 当成“当前元素下标”而不是“下一个写入位置”
  • 忘了题目要求是“原地修改”
  • 26 题里去重时,比较对象写错了
  • 283 题写完非零元素后,忘记处理后面的零,或者交换逻辑写乱
  • 返回数组而不是返回新长度

今天建议你这样练

  1. 先背下来一句话:fast 读,slow 写
  2. 直接做 27,理解最基础模板
  3. 再做 26,体会“有序数组 + 去重”的变种
  4. 最后做 283,体会“保序 + 原地交换”
  5. 晚上不看答案,手写这 3 题的核心循环

后续内容如何设计优化

建议的数据结构

每个 Day 固定 6 个模块

  1. 模板定义:这类题在解决什么问题
  2. 识别信号:看到什么题意想到这个模板
  3. 通用代码模板:JS / 以后也可加 Python
  4. 例题拆解:1~3 道经典题的解法思路
  5. 坑点清单:边界、返回值、指针更新顺序
  6. 复习提示:晚上默写什么、复盘什么

建议的页面形态

  • 顶部保留周视图,方便总览
  • 每个 Day 增加“展开详解”区块
  • 代码块统一支持复制按钮(下一版可加 JS)
  • 每道题都能挂“我的思路 / 易错点 / 一句话总结”
  • 后面可加入本地打卡状态和已完成标记

最适合你的迭代顺序

  1. 先把 Day 1 ~ Day 7 全部补成这种详解版
  2. 再给每道题加题解思路
  3. 再补 JS 模板库总页
  4. 最后加本地打卡、折叠、筛选和搜索

每日执行方式

复健核心:模板驱动

白天

  1. 先看模板 10~15 分钟
  2. 搞清适用场景、识别信号、核心框架、易错点
  3. 刷 3 道必刷题
  4. 有余力再做 1~2 道可选题

晚上

  1. 重做当天最卡的 1~2 道题
  2. 不看答案默写模板
  3. 写一句总结:看到什么信号就该想到这个模板

最低完成标准

  • 每天 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. 找到字符串中所有字母异位词