两种方法解决最小路径和的问题,一种方法是递归(超时),另一种方法是动态规划。其实动态规划和递归原理一样,都是将大问题转化为小问题求解的方法。本题的大小问题关系是:到nums[i][j]的最小路径和等于min(到上方nums[i-1][j]的最小和,到左方nums[i][j-1]的最小和) + nums[i][j]。
一、递归方法
class Solution { public: /** * * @param matrix int整型vector<vector<>> the matrix * @return int整型 */ int minPathSum(vector<vector<int> >& matrix) { // write code here // 用动态规划的方法实现最小路径和的问题 // 原问题:求nums[0][0]到nums[i][j]的最小路径和, 该问题等于nums[i - 1][j]和nums[i][j - 1]的路径和的较小值+nums[i][j] // 子问题就是求nums[i-1][j]和nums[i][j-1]的最小路径和 // 先尝试递归(自顶向下),再尝试动态规划(制表法,自底向上) return dfs(matrix, matrix.size() - 1, matrix[0].size() - 1); } private: // 有别的参数需要传递,所以需要重新写递归函数 int dfs (vector<vector<int>>& matrix, int i, int j) { // i和j分别为矩阵的行坐标和列坐标 if (i == 0 && j == 0) return matrix[0][0]; // 说明nums[i][j]在第一行,则其路径只有一种:从nums[0][0]向右而来,则其路径和 else if (i == 0 && j != 0) return dfs(matrix, i, j-1) + matrix[i][j]; else if (i != 0 && j == 0) return dfs(matrix, i-1, j) + matrix[i][j]; else { return min(dfs(matrix, i-1, j), dfs(matrix, i, j-1)) + matrix[i][j]; // 到左边元素的最小路径和右边最小路径的较小值+当前值 } } };
二、动态规划方法
class Solution { public: int minPathSum(vector<vector<int>>& matrix) { // 将递归转化为动态规划来做 // 自底向上计算最小路径,这样可以避免递归的众多重复计算 int nr = matrix.size(); if (!nr) return 0; int nc = matrix[0].size(); vector<vector<int>> dp(nr, vector<int>(nc)); // nr * nc的数组 dp[0][0] = matrix[0][0]; // 初始化行和列 for (int i = 1; i < nr; i++) { dp[i][0] = dp[i - 1][0] + matrix[i][0]; } for (int i = 1; i < nc; i++) { dp[0][i] = dp[0][i - 1] + matrix[0][i]; } // 一行一行地填充动规数组 for (int i = 1; i < nr; i++) { for (int j = 1; j < nc; j++) { // 对第i行 dp[i][j] = min(dp[i][j-1], dp[i-1][j]) + matrix[i][j]; } } return dp[nr - 1][nc - 1]; } };