您的位置:首页 > 其它

[LeetCode 63] 不同路径 II

2019-03-25 13:22 78 查看

[LeetCode 63] 不同路径 II

题目描述


示例 1:

输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:

  1. 向右 -> 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右 -> 向右

题目分析

这道题的意思就是从左上角的点开始遍历,一直遍历到右下角,如果为1则跳过,如果为0则可以运行。由于这种题要判断状态和状态的转移方程,所以动态规划是最好的方式了。不然也可以用回溯了。

源码

class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
if(obstacleGrid==null){
return 0;
}
int row=obstacleGrid.length;
int col=obstacleGrid[0].length;
if(row==0||col==0){
return 0;
}
//一行一列必定不通
int[][] dp=new int[row][col];
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(obstacleGrid[i][j]==0){
if(i==0&&j==0){
dp[i][j]=1;
}
else if(i==0){
dp[i][j]=dp[i][j-1];
}

else if(j==0){
dp[i][j]=dp[i-1][j];
}
else{
dp[i][j]=dp[i-1][j]+dp[i][j-1];
//把路径全加起来
}
}
}
}
return dp[row-1][col-1];
}
}

改进

思路就是动态规划啦,不过可以去遍历然后一个一个判断。要说用第二种方法的话,我会选择初始化加上递归的思想,虽然其实就是第一种方法的改写啦。

改进代码

int m=obstacleGrid.length,n=obstacleGrid[0].length;
int a[][] = new int[m]
;
int i;
i=0;
//初始化行
while (i < m) {
if(obstacleGrid[i][0]==0){
a[i][0]=1;
}else{
break;
}
i++;
}
while(i<m){
a[i][0]=0;
i++;
}
i=0;
//初始化列
while (i < n) {
if(obstacleGrid[0][i]==0){
a[0][i]=1;
}else{
break;
}
i++;
}
while(i<n){
a[0][i]=0;
i++;
}
//带判断条件的动态规划
for (i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if(obstacleGrid[i][j]==1){
a[i][j]=0;
}else{
a[i][j]=a[i-1][j]+a[i][j-1];
}
}
}
return a[m-1][n-1];
}
}

分析

第一个时间复杂度为O(n^2)
第二个时间复杂度为O(n^2)但是空间复杂度会相对高一点了吧

难点

这道题难度就在于比不同路径I多了一个障碍物。对于不同路径I我可以直接用排列组合的方式来做,这一题就不行了,只能老老实实的动态规划,搞清楚每个状态和状态的转移方程。

小结

这道题的难点就在于搞清楚状态转移方程,遍历时自动避开障碍物,然后障碍物向下向右都是不可能的,所以用条件语句来限制,最后把步数全加起来就行了。

[1]https://leetcode-cn.com/problems/unique-paths-ii/comments/

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: