给一个形状为m x n的矩阵,求从左上角到右下角的不同路径的个数。行进时只能往右/下移动。
- 方法一:使用二维数组存储每个位置的dp值
稍作画图分析即可得到dp式子:dp [i] [j] = dp [i-1] [j] + dp [i] [j-1]
(1)首先,可知若只能往下或往右走,则只能有一条路径。可以先将第一行与第一列进行赋值,再通过循环计算其他格的dp值,防止 i-1 或 j-1 非法(当前i, j格没有上一格/左一格)。注意二维vector的初始化方法。
if(m == 1 || n == 1) // 若 行/列 为1,则必定只有一条路径
return 1;
vector<vector<int>> dp(m, vector<int>(n, 1)); // 二维vector的初始化方法
for(int i=0; i<n; i++) { // 先对第一行赋初值。实际在对dp初始化时已经为所有的值初始化为1
dp[0][i] = 1;
}
for(int i=0; i<m; i++) { // 对第一列
dp[i][0] = 1;
}
(2)根据dp [i] [j] = dp [i-1] [j] + dp [i] [j-1], 循环得到其他dp值。
for(int i=1; i<m; i++) {
for(int j=1; j<n; j++) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
最后再返回 dp [m-1] [n-1] ,即是走到右下角的路径数。不要误写为dp [m] [n],会导致越界。
总代码:
class Solution {
public:
int uniquePaths(int m, int n) {
if(m == 1 || n == 1)
return 1;
vector<vector<int>> dp(m, vector<int>(n, 1)); // (1)初始状态值
/* 以下内容可不用
for(int i=0; i<n; i++) {
dp[0][i] = 1;
}
for(int i=0; i<m; i++) {
dp[i][0] = 1;
}
*/
for(int i=1; i<m; i++) { // (2)基于初始状态值和dp公式,计算其他位置的值
for(int j=1; j<n; j++) {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
return dp[m-1][n-1]; // (3)返回右下角的dp值
}
};
- 方法二:优化内存空间,使用一维数组存储
每一处的位置仅与左侧和上侧相关,使用一个一维数组dp,当前位置为dp[j],左侧即为dp[j-1],上侧即为dp[j](未更新dp[j]之前,这一位置即是上一行的j处)。
所以更新规则变为:dp[j] = dp[j-1] + dp[j],初始化为1。
总代码如下:
int uniquePaths(int m, int n) {
if(m == 1 || n == 1)
return 1;
vector<int> dp(n, 1); // 使用一维数组
for(int i=1; i<m; i++) {
for(int j=1; j<n; j++) {
dp[j] = dp[j-1] + dp[j]; // 更新规则
}
}
return dp[n-1]; // 返回最后一个位置即为右下角的位置
}