文章目录
题目解析
算法原理
- 状态表示
对于这种「路径类」的问题,我们的状态表示⼀般有两种形式:
i. 从[i, j] 位置出发。
ii. 从起始位置出发,到[i, j] 位置。
这⾥选择第⼆种定义状态表⽰的⽅式:
dp[i][j] 表示:⾛到[i, j] 位置处,⼀共有多少种⽅式。 - 状态转移⽅程:
简单分析⼀下。如果dp[i][j] 表示到达[i, j] 位置的⽅法数,那么到达[i, j] 位置之
前的⼀小步,有两种情况:
i. 从[i, j] 位置的上方( [i - 1, j] 的位置)向下走⼀步,转移到[i, j] 位置;
ii. 从[i, j] 位置的左方( [i, j - 1] 的位置)向右走⼀步,转移到[i, j] 位置。
由于我们要求的是有多少种⽅法,因此状态转移⽅程就呼之欲出了:
dp[i][j] = dp[i - 1][j] + dp[i][j - 1] 。 - 初始化:
可以在最前⾯加上⼀个「辅助结点」,帮助我们初始化。使⽤这种技巧要注意两个点:
i. 辅助结点⾥⾯的值要「保证后续填表是正确的」;
ii. 「下标的映射关系」。
在本题中,「添加⼀⾏」,并且「添加⼀列」后,只需将dp[0][1] 的位置初始化为1 即可。 - 填表顺序:
根据「状态转移⽅程」的推导来看,填表的顺序就是「从上往下」填每⼀⾏,在填写每⼀⾏的时候「从左往右」。 - 返回值:
根据「状态表示」,我们要返回dp[m][n] 的值。
代码实现
java
class Solution {
public int uniquePaths(int m, int n)
{
int[][] dp=new int[m+1][n+1];
//dp数组加一行和加一列是防止dp[i-1]越界访问
dp[0][1]=1;//因为数组的一行和第一列的元素必须要等于1,为什么是1,因为机器人只能
//向右或者向下移动走第一行和第一列的时候只有一种方式,所以是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][n];
}
}
题目练习
java
class Solution
{
public int uniquePathsWithObstacles(int[][] ob)
{
int m = ob.length, n = ob[0].length;
int[][] dp = new int[m + 1][n + 1];
dp[1][0] = 1;//第一行第一列设置为1,因为第一行和第一列都只能左移或者向下移动,只有一种方式,所以设置为1
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
if(ob[i - 1][j - 1] == 0)//因为数组初始化为int[m + 1][n + 1];原来的[0][0]下标变为了[1][1]下标,
//下标的映射关系发生了改变
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
return dp[m][n];
}
}
完。