📟作者主页:慢热的陕西人
🌴专栏链接:力扣刷题日记
📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言
文章目录
- 牛客热题:不同的路径数目(一)
- 题目链接
- 方法一:二维dp
- 思路
- 代码
- 复杂度
- 方法二:组合数学
- 思路
- 代码
- 复杂度
牛客热题:不同的路径数目(一)
题目链接
不同路径的数目(一)_牛客题霸_牛客网 (nowcoder.com)
方法一:二维dp
思路
① 状态表示:
d p [ i ] [ j ] dp[i][j] dp[i][j]记录到达第 i i i行 j j j列的方法数
②初始化:
首先第一列和第一行的到达方法均只有一种,因为我们只能从它的上方或者左方到达,因此只有一条路径,所以我们将第一列和第一行均初始化为1
③状态转移:
对于每一个位置(除了第一行第一列),都有两种到达的方法,从上方和从左方到达。
所以状态转移方程为: d p [ i ] [ j ] dp[i][j] dp[i][j] = d p [ i − 1 ] [ j ] + d p [ i ] [ j − 1 ] dp[i - 1][j] + dp[i][j - 1] dp[i−1][j]+dp[i][j−1]
④填表顺序:
因为状态转移方程中需要依赖左侧和上方的状态,所以我们的填表顺序是从上到下,从左到右的。
⑤返回答案:
因为我们需要的是从起点到终点的路径方法,所以我们最终返回对应的 d p [ m − 1 ] [ n − 1 ] dp[m - 1][n - 1] dp[m−1][n−1]就可以了。
代码
int uniquePaths(int m, int n)
{
vector<vector<int>> dp(m, vector<int>(n, 0));
//初始化
dp[0][0] = 1;
for(int i = 1; i < m || i < n; ++i)
{
if(i < m) dp[i][0] = 1;
if(i < n) dp[0][i] = 1;
}
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];
}
return dp[m - 1][n - 1];
}
复杂度
时间复杂度:遍历二维数组 O ( m ∗ n ) O(m * n) O(m∗n)
空间复杂度:创建了一个二维的dp数组 O ( m ∗ n ) O(m * n) O(m∗n)
方法二:组合数学
思路
由于在矩阵中没有障碍物,从左左上角移动到右下角一共要移动m+n-2次,其中有m-1次向下,n-1次向右,对这两种操作进行组合。因此最后就是求 C ( m − 1 n + m − 2 ) C\binom{m - 1}{n + m - 2} C(n+m−2m−1)这个组合数
代码
int uniquePaths(int m, int n)
{
long long ret = 1;
for(int x = n, y = 1; y < m; ++x, ++y)
{
ret = ret * x / y;
}
return ret;
}
复杂度
时间复杂度:O(min(m, n)), 我们计算组合数的时候,只需要一次遍历就可以计算出结果。
空间复杂度:O(1), 没有使用额外的变量。