news 2026/10/27 12:15:40

力扣hot100多维动态规划解题技巧与实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
力扣hot100多维动态规划解题技巧与实战

1. 多维动态规划在力扣hot100中的核心地位

第一次接触力扣hot100的多维动态规划问题时,我盯着那道"不同路径"的题目整整半小时没写出一行代码。后来才发现,这类问题在面试中的出现频率高得惊人——根据2023年头部互联网企业的面试题库统计,涉及二维及以上状态转移的DP问题占比超过35%。

多维动态规划之所以成为hot100的常客,本质上是因为它能完美模拟现实中的复杂决策过程。比如经典的"最小路径和"问题,其实就是项目资源分配场景的抽象;而"编辑距离"则直接对应着文本处理中的实际需求。这些题目把工作中的复杂问题,用矩阵和状态转移方程的形式优雅地表达出来。

2. 解题框架与思维模型构建

2.1 状态定义的双重维度

处理二维DP时,我习惯先在草稿纸上画出矩阵图。以第64题"最小路径和"为例:

示例矩阵: [ [1,3,1], [1,5,1], [4,2,1] ]

定义dp[i][j]表示走到(i,j)时的最小路径和。这个定义看似简单,但要注意两个关键点:

  1. 维度对齐:矩阵的行列索引与问题描述的坐标系要严格对应
  2. 状态含义:每个状态要完整包含当前决策所需的所有历史信息

新手常犯的错误是状态定义不全,比如试图用一维数组解决二维问题,结果无法处理来自上方和左方的双重转移。

2.2 状态转移方程的三要素

写出正确的状态转移方程需要同时考虑:

  1. 转移方向(通常来自上方或左方)
  2. 边界条件(第一行/列的特殊处理)
  3. 决策依据(取最小值/最大值或累加)

以Python实现为例:

def minPathSum(grid): m, n = len(grid), len(grid[0]) dp = [[0]*n for _ in range(m)] dp[0][0] = grid[0][0] # 初始化第一列 for i in range(1, m): dp[i][0] = dp[i-1][0] + grid[i][0] # 初始化第一行 for j in range(1, n): dp[0][j] = dp[0][j-1] + grid[0][j] for i in range(1, m): for j in range(1, n): dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j] return dp[-1][-1]

2.3 空间优化的滑动窗口技巧

当发现状态转移只依赖相邻的前几个状态时,就可以进行空间优化。比如"最小路径和"可以压缩到O(n)空间:

def minPathSum(grid): m, n = len(grid), len(grid[0]) dp = [0]*n dp[0] = grid[0][0] for j in range(1, n): dp[j] = dp[j-1] + grid[0][j] for i in range(1, m): dp[0] += grid[i][0] for j in range(1, n): dp[j] = min(dp[j], dp[j-1]) + grid[i][j] return dp[-1]

这种优化在面试中能显著加分,因为它展示了对算法本质的深刻理解。

3. hot100经典题型深度剖析

3.1 第72题:编辑距离

这道题堪称多维DP的典范,它定义了三个操作维度(插入、删除、替换)。状态转移方程:

dp[i][j] = min( dp[i-1][j] + 1, # 删除 dp[i][j-1] + 1, # 插入 dp[i-1][j-1] + (0 if word1[i-1]==word2[j-1] else 1) # 替换 )

实际实现时要注意字符串索引偏移:

def minDistance(word1, word2): m, n = len(word1), len(word2) dp = [[0]*(n+1) for _ in range(m+1)] for i in range(m+1): dp[i][0] = i for j in range(n+1): dp[0][j] = j for i in range(1, m+1): for j in range(1, n+1): if word1[i-1] == word2[j-1]: dp[i][j] = dp[i-1][j-1] else: dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) return dp[m][n]

3.2 第221题:最大正方形

这道题需要发现隐藏的状态转移规律。定义dp[i][j]表示以(i,j)为右下角的最大正方形边长:

dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1

当matrix[i][j]=='1'时成立

实现时需要特别注意边界条件:

def maximalSquare(matrix): if not matrix: return 0 m, n = len(matrix), len(matrix[0]) dp = [[0]*n for _ in range(m)] max_len = 0 for i in range(m): for j in range(n): if matrix[i][j] == '1': if i == 0 or j == 0: dp[i][j] = 1 else: dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + 1 max_len = max(max_len, dp[i][j]) return max_len * max_len

4. 调试技巧与常见陷阱

4.1 矩阵初始化陷阱

创建二维DP数组时,绝对不要用[[0]*n]*m这种方式!这会导致所有行引用同一个列表。正确做法是:

# 正确 dp = [[0]*n for _ in range(m)] # 错误(所有行实际是同一个列表) dp = [[0]*n]*m

4.2 边界条件验证

我习惯先单独处理第一行和第一列,再处理内部元素。例如在"不同路径II"中:

# 初始化第一列 for i in range(m): if obstacleGrid[i][0] == 1: break dp[i][0] = 1 # 初始化第一行 for j in range(n): if obstacleGrid[0][j] == 1: break dp[0][j] = 1

4.3 状态转移可视化

对于复杂的问题,我建议打印中间状态。比如在调试"编辑距离"时,可以这样观察DP表:

def print_dp(dp, word1, word2): print(' ' + ' '.join([' '] + list(word2))) for i in range(len(dp)): prefix = ' ' if i==0 else word1[i-1] print(prefix, dp[i])

5. 面试实战策略

5.1 问题拆解四步法

  1. 明确状态含义(向面试官确认理解)
  2. 确定初始状态(特别是边界条件)
  3. 推导状态转移方程(用具体例子验证)
  4. 讨论空间优化可能(展示深度思考)

5.2 白板编码技巧

  • 先写出空函数框架
  • 注释说明每个步骤的意图
  • 处理完边界条件后立即举例验证
  • 最后讨论时间/空间复杂度

5.3 高频follow-up问题

  1. 如何修改算法处理更大规模数据?
  2. 如果需要输出具体路径而不仅是数值结果?
  3. 如果允许额外的操作(如交换字符)?
  4. 如何用记忆化搜索替代DP表格?

6. 进阶训练建议

从hot100出发,我推荐按这个路线进阶训练:

  1. 基础二维DP:64、72、120
  2. 带障碍物的变种:63、174
  3. 字符串处理:97、115
  4. 背包问题变种:1049(其实是二维问题)
  5. 状态压缩DP:576(三维降二维)

每周重点攻克一个类型,记录每道题的思考时间和bug点。我自己的错题本显示,二维DP的平均debug时间从最初的2小时缩短到了现在的15分钟,这就是刻意训练的效果。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/27 12:15:34

PyTorch手写ResNet-50:从残差连接到Bottleneck实现详解

1. 项目概述:这不是一个“调包跑通”的Demo,而是一次对ResNet-50底层逻辑的亲手拆解 你在网上搜“PyTorch ResNet-50”,十有八九会看到一段不到20行的代码: model torchvision.models.resnet50(pretrainedTrue) ,然…

作者头像 李华
网站建设 2026/10/27 12:15:20

新手用AI做项目:从需求拆解到代码落地的完整指南

1. 先想清楚:新手用AI做项目,卡点到底在哪 很多人一提到"用AI做个人项目",脑子里第一反应是打开某个AI编程工具,敲一句"帮我写一个记账App",然后等着代码哗哗往外冒。我刚开始也是这么想的&#x…

作者头像 李华
网站建设 2026/10/27 12:15:08

OpenAI DevDay 2026 深度拆解:dots、ChatGPT Spaces 与 GPT-6.1 Sol 开发实战

1. 这场发布会到底讲了什么:从标题拆解核心看点OpenAI DevDay 2026 一口气甩出 20 多项发布,信息密度大到很多人看完直播第一反应是"记不住"。我把整场内容反复过了几遍,把最值得普通开发者和产品团队关注的东西拎出来,…

作者头像 李华
网站建设 2026/10/27 12:14:52

MySQL数据库课程实验工程化:建库脚本、选课事务与索引优化

简介:面向学习数据库系统课程的高校学生与自学者,这份资料对应悉尼大学 COMP9120 数据库管理系统课程,聚焦从概念建模、关系模型与关系代数到 SQL 编写、事务与并发控制、规范化设计、存储索引和查询处理等核心主题,适合课程同步学…

作者头像 李华
网站建设 2026/10/27 12:12:12

ChatGPT高效工作流:提示词、文本流水线与结构化整理实战

上个月有个做运营的朋友跟我吐槽,说他用了两周 ChatGPT,效率不升反降,原本两小时能写完的周报,现在要花三个小时跟它来回拉扯。我让他把聊天记录发我看看,翻了几页就明白了:他每一句都是“帮我写个周报”“…

作者头像 李华
网站建设 2026/10/27 12:10:39

Docker报错no command specified:根因、排查与五种修复方案

docker: Error response from daemon: no command specified.这行报错,我这些年至少撞见过上百回,场景几乎一模一样:docker run敲下去、回车、终端原样吐回这一句,容器连个影子都没留下。它的字面意思很直白——Docker 守护进程在…

作者头像 李华