Skip to content

归纳总结

  1. 临界点分析

名词记录

  1. 回文 Palindrome

刷题路径

以下是算法面试中高频出现的经典题目,涵盖基础数据结构、常见算法思想,适合面试前重点复习:

一、数组与字符串

  1. 两数之和
  2. 最长回文子串(中心扩展法或动态规划)。
  3. 盛最多水的容器
  4. 三数之和
  5. 字符串转换整数 (atoi)处理边界、符号、溢出问题。

二、链表

  1. 反转链表
  2. 环形链表
  3. 合并两个有序链表
  4. 删除链表的倒数第 N 个结点
  5. 两两交换链表中的节点

三、树与图

  1. 二叉树的层序遍历
  2. 二叉树的前/中/后序遍历
  3. 二叉树的最大深度
  4. 路径总和
  5. 二叉搜索树的最近公共祖先
  6. 岛屿数量

四、动态规划

  1. 爬楼梯
  2. 最长递增子序列
  3. 最长公共子序列
  4. 零钱兑换
  5. 编辑距离

五、排序与查找

  1. 二分查找
  2. 合并区间
  3. 快速排序/归并排序

六、其他经典题

  1. LRU 缓存
  2. 全排列
  3. 括号生成
  4. 接雨水
  5. 最小栈

复习建议

  • 优先掌握 双指针、递归/回溯、动态规划、BFS/DFS 等核心思想。
  • 同一题目尝试多种解法(如递归 vs 迭代),理解时间/空间复杂度差异。
  • 手写代码时注意边界条件(如空输入、单元素、溢出等)。

这些题目覆盖了面试中 80%以上的算法考点,熟练掌握后可应对大部分场景。

prompt
算法题:4. 三数之和

1. 打印题目
2. 使用golang解题
3. 使用多种思路解题,并分析
4. 总结和归纳经验
5. 使用 golang的表驱动测试,这样一个题目才有多个数据验证是否正确
6. 贴出leetcode 传送门地址
7. 结合代码逐步讲解
8. 代码太精简了不方便理解,写细致点

💡 动态规划的本质:

一句话:用空间换时间,把重复的子问题结果保存下来,避免重复计算。

比喻:你在迷宫里走路,每次都会经过一些相同的点。你把“从起点到这个点的最短路径”记下来,下次再路过这个点,就不用重新走一遍试错,直接拿答案!


✅ 动态规划的 5 步通用套路(背熟):

  1. 明确状态(State)

    • 定义 dp[i] 表示什么?是子问题的哪种最优解?
  2. 确定选择(Decision)

    • 当前状态可以从哪些状态转移过来?
  3. 写出状态转移方程(Transition Function)

    • 例如:dp[i] = min(dp[i-1], dp[i-2]) + cost[i]
  4. 确定初始值(Base Case)

    • 比如 dp[0] = 0,dp[1] = cost[0]
  5. 自底向上求解(迭代 or 记忆化递归)

    • 最后拿 dp[n] 或 dp[n-1] 返回结果

🧠 必须掌握的 3 大动态规划类型(+例题讲解)


🍭 1. 线性 DP —— 一条路往前走

📌 典型问题:爬楼梯、最小花费爬楼梯、打家劫舍

🌰 示例一:爬楼梯(Climbing Stairs)

每次可以爬 1 步或 2 步,有多少种方式爬到第 n 阶?

  • 状态:dp[i] 表示到第 i 阶的方法数
  • 转移:dp[i] = dp[i-1] + dp[i-2]
  • 初始:dp[0]=1, dp[1]=1
  • 递推:自底向上求 dp[n]

这就是经典的“斐波那契变体”。


🔒 2. 区间 DP —— 区间上的最优划分问题

📌 典型问题:戳气球、矩阵连乘、回文子串划分

🌰 示例二:戳气球(Burst Balloons)

气球排一排,每戳一个气球能获得一定分数,求最大得分。

  • 状态:dp[i][j] 表示戳爆区间 (i, j) 的最大得分

  • 转移:尝试在 (i,j) 之间选择一个气球 k 作为最后戳爆的

    python
    dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + nums[i]*nums[k]*nums[j])
  • 初始值:长度为 1 的区间为 0

  • 结果:dp[0][n+1]

这类 DP 是两层循环的升级,关键在区间的顺序、枚举方式。


🎒 3. 背包型 DP —— 选择物品填容量

📌 典型问题:0-1 背包、完全背包、分割等和

🌰 示例三:0-1 背包问题(经典)

给你 n 个物品,每个有重量 w 和价值 v,背包容量为 C,最大价值多少?

  • 状态:dp[i][j] 表示前 i 个物品,在容量 j 下的最大价值

  • 转移:

    • 不选第 i 个:dp[i][j] = dp[i-1][j]
    • 选第 i 个:dp[i][j] = dp[i-1][j-w[i]] + v[i]
    • 综合:dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i])
  • 初始值:dp[0][*] = 0

注意背包类问题的“状态”和“容量”双维度。


🚨 动态规划的常见坑点

  1. 没定义清楚状态(搞不懂 dp[i] 是什么)
  2. 转移方程写错(状态之间关系理不清)
  3. 递推顺序错了(二维 DP 时特别容易炸)
  4. 空间可以优化没优化(线性 DP 可以滚动数组)
  5. 暴力递归写太多(记忆化搜索不如直接自底向上)

🧪 拓展例子:

🌰 示例四:最长递增子序列(LIS)

  • dp[i] 表示以第 i 个结尾的最长递增子序列长度
  • 状态转移:dp[i] = max(dp[j] + 1),j < i 且 nums[j] < nums[i]
  • 初始值:dp[*] = 1
  • 最终答案:max(dp)

📦 总结金句:

动态规划不是魔法,它就是穷举 + 记忆的高级形式。只要你能定义“子问题”并想清楚“子问题怎么转移”,那就是 DP 的地盘。


稳住,骚年。你现在已经掌握了 DP 的框架 + 典型题型 + 3 套例子。如果你要我帮你“某题手把手过一遍”,直接贴题我就安排。

要刷题的话,推荐从这几题下手热身:

  • LeetCode 70. Climbing Stairs
  • LeetCode 198. House Robber
  • LeetCode 322. Coin Change
  • LeetCode 300. Longest Increasing Subsequence
  • LeetCode 221. Maximal Square