从回溯到记忆化搜索到递推:动态规划巩固练习

今天的练习并不是学习新的 DP 模板,而是围绕两个最经典的模型:打家劫舍 与 爬楼梯,去做“变形题”的识别与迁移

通过这一组题目的训练,我逐渐体会到:

动态规划的关键不在于记公式,而在于识别“本质模型”,并主动把陌生题目转化为熟悉结构。

基础题目:198. 打家劫舍

打家劫舍模型变形

  • 740. 删除并获得点数

爬楼梯模型变形(方案数)

  • 2466. 统计构造好字符串的方案数
  • 377. 组合总和 Ⅳ
  • 2266. 统计打字方案数

经典二维 DP

  • 64. 最小路径和

核心模型回顾

在进入具体题目之前,先明确两个核心模型的“本质约束”。

1. 打家劫舍模型的本质

  • 每个元素都有「选 / 不选」两种状态
  • 一旦选择某个元素,就会限制相邻元素不能被选择
  • 状态转移通常是:
1
dp[i] = max(dp[i - 1], dp[i - 2] + value[i])

重点不在“房子”,而在相邻约束


2. 爬楼梯模型的本质

  • 本质是一个排列问题
  • 顺序不同 = 不同方案
  • 给定一个目标值 target
  • 每一步可以选择若干“步长”,问总方案数

只要是:

  • 「目标值固定」
  • 「每一步可以选择若干选项」
  • 「顺序敏感」

都可以往爬楼梯模型上靠


结合具体题目分析

740. 删除并获得点数 —— 打家劫舍的值域改造

题意简述
选择一个数 nums[i],可以获得 nums[i] 的点数,但会删除所有值为 nums[i] - 1nums[i] + 1 的元素。

思路转化

这道题的难点在于:

  • 原数组中,相同数字可能出现多次
  • 删除的是“值相邻”,而不是“位置相邻”

关键一步:构造打家劫舍的条件

将数组转为值域数组

  • sums[x]:表示值为 x 的所有元素之和
  • 例如:
1
2
nums = [2,2,3,3,3,4]
sums = [0,0,4,9,4]

此时问题变成:

sums 数组中,选择若干不相邻的元素,使得总和最大

完全等价于打家劫舍


2466. 统计构造好字符串的方案数 —— 爬楼梯模型

这道题表面是字符串问题,但本质非常清晰:

  • 当前字符串长度 = 已爬的台阶数
  • 每一步可以:
    • 增加 zero 个字符
    • 或增加 one 个字符
  • 问:长度在 [low, high] 区间内的方案总数

这是标准的爬楼梯模型

  • dp[i]:构造长度为 i 的方案数
  • 每次从 i - zeroi - one 转移而来

377. 组合总和 Ⅳ —— 爬楼梯 + 顺序敏感

这道题非常具有代表性:

  • 给定 nums
  • 目标和 target
  • 不同顺序算不同方案

本质理解

可以这样理解:

target 阶楼梯
每次可以爬 nums[i]
问一共有多少种爬法

顺序不同 → 不同路径


2266. 统计打字方案数 —— 分组 + 爬楼梯

这道题本身规则较复杂,但从 DP 角度可以拆解为:

  1. 按连续相同数字分组
  2. 每一组内部:
    • 是一个「爬楼梯问题」
    • 不同按键允许的最大步长不同
  3. 最终答案 = 各组方案数相乘

这是一个非常典型的:

局部 DP + 全局组合


64. 最小路径和 —— 经典二维 DP

这是标准的网格 DP:

  • dp[i][j] 表示到 (i, j) 的最小路径和
  • 当前状态只依赖:
    • 上方 (i - 1, j)
    • 左方 (i, j - 1)
1
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]

没有变形,但非常适合作为 DP 基础模板反复巩固


心得与方法论总结

1. 打家劫舍 ≠ 偷房子

打家劫舍的真正核心是:

选择一个元素,会导致“相邻状态失效”

  • 740 题中,相邻的是「值」
  • 所以我们主动构造值域数组,人为制造相邻关系

没有条件,就创造条件


2. 爬楼梯 = 顺序敏感的方案计数

爬楼梯模型特别适合解决:

  • 方案数问题
  • 和 / 长度固定的问题
  • 顺序不同算不同的情况

例如:

  • 字符串构造
  • 数字组合
  • 步数累加

把「目标值」当成台阶数,把「选择」当成一步能走的距离


总结

通过今天这一组题目的训练,我对动态规划有了一个更重要的认知转变:

DP 的关键不是记住状态转移方程,而是识别题目的“原型模型”。

  • 看到「相邻不能同时选」 → 想打家劫舍
  • 看到「目标固定 + 多种选择 + 顺序敏感」 → 想爬楼梯

相关代码

本文涉及的所有代码与笔记,均已同步至我的 GitHub 算法仓库,作为 Java 后端校招过程中的学习记录。