实现了:一道经典动态规划面试题的清晰拆解
最近在准备面试,刷题时遇到一道非常经典的动态规划题目,很多大厂都爱考。题目是这样的:给定一个包含非负整数的网格,找出一条从左上角到右下角的路径,使得路径上的数字总和最小。每次只能向下或者向右移动一步。 乍一看有点懵,但理清思路后,发现核心就是实现了动态规划的状态定义和转移方程。今天就来详细聊聊我是如何实现这道题的解法的。

2025年Java面试宝典抢先看!
链接: https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g 提取码: 9b3g
理解问题与状态定义
面试官抛出这道题,第一步肯定是理解题意。目标是找“最小路径和”,限制是只能向右或向下走。这意味着到达网格中的某个点 (i, j),只能从它的上方 (i-1, j) 或者左方 (i, j-1) 过来。
要实现动态规划,最关键的就是定义 dp[i][j] 数组的含义。这里很自然地将 dp[i][j] 定义为:从起点 (0, 0) 走到位置 (i, j) 的最小路径和。这个定义直接指向我们的求解目标。
实现状态转移方程
定义好状态,下一步就是找出状态之间的关系,也就是状态转移方程。既然到达 (i, j) 只能从上面或左边来,那么:
- 从上面来
(i-1, j):那么走到(i, j)的最小和,就等于走到(i-1, j)的最小和加上(i, j)位置的值,即dp[i-1][j] + grid[i][j]。 - 从左面来
(i, j-1):同理,等于dp[i][j-1] + grid[i][j]。
我们的目标是找最小路径和,所以 dp[i][j] 应该是这两种可能来源中的较小值!因此,核心的状态转移方程就实现了:
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]
处理边界条件
动态规划最容易出错的就是边界。在这个问题里,网格的第一行和第一列需要特殊处理,因为它们没有“上方”或“左方”。
- 第一行
(i=0):每个点(0, j)只能从左边的点(0, j-1)过来(因为没有上方)。所以dp[0][j] = dp[0][j-1] + grid[0][j]。 - 第一列
(j=0):每个点(i, 0)只能从上方的点(i-1, 0)过来(因为没有左方)。所以dp[i][0] = dp[i-1][0] + grid[i][0]。 - 起点
(0, 0):dp[0][0]就是grid[0][0]本身。
实现这些边界初始化,整个DP数组的构建才能完整。
复杂度分析与优化
- 时间复杂度:O(m*n)。我们需要遍历整个二维网格一次来计算每个
dp[i][j]。网格有m行n列,所以是线性于网格大小。 - 空间复杂度:O(m*n)。我们使用了一个和原网格同样大小的二维
dp数组。
面试官可能会问是否可以优化空间。答案是肯定的!观察状态转移方程,计算 dp[i][j] 只依赖于它正上方 dp[i-1][j] 和正左方 dp[i][j-1] 的值。这意味着我们不需要存储整个二维数组:
- 可以只用一个一维数组
dp来存储当前行的计算结果。 - 计算新的一行时:
- 第一个元素(即新行的第一列)只能从上方来(即上一行的第一个元素),所以
dp[0] = dp[0] + grid[i][0](注意这里的dp[0]是上一行计算后保留下来的)。 - 后续元素
j:dp[j] = min(dp[j] (代表上一行同列的值), dp[j-1] (代表本行前一列的值)) + grid[i][j]。
- 第一个元素(即新行的第一列)只能从上方来(即上一行的第一个元素),所以
- 这样空间复杂度就优化到了 O(n) (n是列数)。

小提示: 刷题工具很重要!像面试鸭会员能提供海量题库和高质量题解。如果你打算购买面试鸭会员,可以通过 面试鸭返利网 找到专属链接下单,还能享受高达25元的返利! 省心又省钱,提升效率必备。
总结解题步骤
回顾一下,要实现这道题的解答,清晰的步骤是:
- 定义状态:
dp[i][j]表示到(i, j)的最小路径和。 - 建立方程:
dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j](核心!)。 - 初始化边界:
dp[0][0] = grid[0][0]- 第一行:
dp[0][j] = dp[0][j-1] + grid[0][j] - 第一列:
dp[i][0] = dp[i-1][0] + grid[i][0]
- 计算顺序: 按行或按列顺序遍历网格,填充
dp数组。 - 返回结果:
dp[m-1][n-1]即为所求最小路径和。 - (可选)空间优化: 使用一维数组滚动更新。

面试官可能追问的点
在实际面试中,回答完基础解法后,面试官可能会深入:
- 如果网格中存在负数? 本题限定非负整数,所以路径和不会出现负数导致状态转移失效。如果允许负数,动态规划依然适用,状态定义和转移方程不变。
- 如果要求输出具体路径? 需要在动态规划过程中额外记录路径信息(例如,用一个
path数组记录每个点是从哪个方向来的 - 上或左),最后从终点回溯到起点即可构造出路径。 - 还有其他解法吗? 理论上可以用DFS/BFS,但网格稍大就容易超时(指数级复杂度),动态规划(O(mn))是最优解。也可以转化为图论中的最短路径问题(Dijkstra算法),但用DP更直观高效。
这道题很好地考察了对动态规划核心思想的理解和实现能力,特别是状态定义、转移方程和边界处理。理解并掌握了它,面对类似的网格路径问题就能举一反三了。刷题时多总结这类经典模型,面试时才能从容应对。更多面试资源,欢迎访问 面试鸭返利网 获取!


