2.4路径问题专题:LeeCode 931.下降路径最小和

发布于:2025-04-04 ⋅ 阅读:(38) ⋅ 点赞:(0)

动态规划解决最小下降路径和问题

1. 题目链接

LeetCode 931. 最小下降路径和

2. 题目描述

给定一个 n x n 的整数矩阵 matrix,找到一条从第一行到最后一行的下降路径,使得路径上的数字和最小。下降路径可以从第一行的任意元素出发,每一步可以选择位于下一行正下方、左下方或右下方的元素。例如,位于 (i, j) 的元素可以下降到 (i+1, j-1)(i+1, j)(i+1, j+1)

3. 示例分析

示例输入

matrix = [[2,1,3],
          [6,5,4],
          [7,8,9]]

输出13
解释:最小下降路径为 1 → 5 → 7,路径和为 1 + 5 + 7 = 13

4. 算法思路

动态规划(Dynamic Programming)

使用动态规划解决该问题的核心思想是:定义 dp[i][j] 表示从第一行到达第 i 行第 j 列的最小路径和。为了处理边界条件(如矩阵边缘的列),我们扩展 dp 数组的边界,使其维度为 (n+1) x (n+2)

状态转移方程

对于每个位置 (i, j),其路径和的最小值由上一行的三个可能的位置决定:

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

其中,matrix[i-1][j-1] 是当前位置的值,dp[i-1][...] 是上一行左、中、右三个位置的路径和的最小值。

初始化
  • dp[0][...] = 0:第一行的所有位置初始化为0,表示从虚拟的第0行出发的路径和为0。
  • 其余位置初始化为 INT_MAX,表示尚未计算。

5. 边界条件与注意事项

  1. 矩阵大小为1的情况:当 n=1 时,直接返回矩阵中唯一的元素。
  2. 索引转换:由于 dp 数组比原矩阵多一圈,访问 matrix 时需要将索引调整为 i-1j-1
  3. 处理边缘列:在矩阵的最左列(j=1)和最右列(j=n),需要确保不会访问到无效的列(如 j=0j=n+1),此时这些位置的 dp 值为 INT_MAX,不影响取最小值。

6. 代码实现

class Solution {
public:
    int minFallingPathSum(vector<vector<int>>& matrix) {
        int n = matrix.size();
        vector<vector<int>> dp(n + 1, vector<int>(n + 2, INT_MAX));
        // 初始化:从虚拟的第0行出发,路径和为0
        for (int j = 0; j < n + 2; j++) dp[0][j] = 0;

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                // 状态转移:取上一行左、中、右的最小值
                dp[i][j] = matrix[i - 1][j - 1] + 
                           min(min(dp[i - 1][j - 1], dp[i - 1][j]), dp[i - 1][j + 1]);
            }
        }

        // 遍历最后一行,寻找最小值
        int ret = INT_MAX;
        for (int j = 0; j < n + 2; j++) {
            ret = min(ret, dp[n][j]);
        }
        return ret;
    }
};

代码解释

  1. 初始化 dp 数组:第0行初始化为0,其他位置为 INT_MAX
  2. 填充 dp 数组:遍历每一行,根据上一行的三个相邻位置的最小值更新当前值。
  3. 获取结果:遍历最后一行的所有列,找到最小值作为最终结果。

通过这种动态规划的方式,时间复杂度为 O(n²),空间复杂度为 O(n²),能够高效解决该问题。


网站公告

今日签到

点亮在社区的每一天
去签到