给定一个m*n的地图,其中加入了一些障碍。每次只能向下或者向右走,问从左上角走到右下角有多少不同的路径?
分别用0和1代表空区域和障碍
例如
下图表示有一个障碍在3*3的图中央。
[ [0,0,0], [0,1,0], [0,0,0] ]有2条不同的路径
备注:m和n不超过100.
class Solution { public: int uniquePathsWithObstacles(vector<vector<int> > &a) { int i, j, m = a.size(), n = a[0].size(); vector<vector<int> > dp(m, vector<int>(n, 0)); // 初始化成0 // 第一个格点的值与障碍数相反 dp[0][0] = 1 - a[0][0]; // 依次计算 for(i = 0; i < m; ++i) { for(j = 0; j < n; ++j) { // 只有没有障碍才有通路 if(a[i][j] == 0) { if(i == 0 && j != 0) dp[0][j] = dp[0][j - 1]; // 左 else if(i != 0 && j == 0) dp[i][0] = dp[i - 1][0]; // 上 else if(i != 0 && j != 0) dp[i][j] += dp[i - 1][j] + dp[i][j - 1]; // 左+上 } } } return dp[m - 1][n - 1]; } };
public class Solution { //初始化两个for循环赋值可以免去,空间复杂度可以降到一维 //个人觉得直接修改输入数据应该不是很合适的做法 public int uniquePathsWithObstacles(int[][] obstacleGrid) { int rowLen = obstacleGrid.length; int colLen = obstacleGrid[0].length; int[] res = new int[colLen + 1]; res[1] = 1; for (int i = 1; i <= rowLen; i++) { for (int j = 1; j <= colLen; j++) { if (obstacleGrid[i - 1][j - 1] == 0) { //res[i]保存的是上一行的值,当前值直接用左边的值加上上一行的值 res[j] += res[j - 1]; } else { res[j] = 0; } } } return res[colLen]; } }
class Solution { public: int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) { if(obstacleGrid.empty()){ return 0; } int m = obstacleGrid.size(); int n = obstacleGrid[0].size(); vector<vector<int>> F(m, vector<int>(n, 0)); for(int i = 0; i < m; ++i){ if(obstacleGrid[i][0] == 1){ break; } F[i][0] = 1; } for(int j = 0; j < n; ++j){ if(obstacleGrid[0][j] == 1){ break; } F[0][j] = 1; } for(int i = 1; i < m; ++i){ for(int j = 1; j < n; ++j){ if(obstacleGrid[i][j] == 1){ F[i][j] = 0; } else{ F[i][j] = F[i - 1][j] + F[i][j - 1]; } } } return F[m - 1][n -1]; } };
/* * 目的:找路径,找路径的拓展 * 方法:动态规划 */ //方法一:使用二维dp,时间复杂度为O(n^2),空间复杂度为O(n^2) int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) { int row = obstacleGrid.size(); if (row==0) return 0; int col = obstacleGrid[0].size(); vector<vector<int>>dp(row,vector<int>(col,1)); for (int i = 0; i < row;++i){ if (obstacleGrid[i][0] == 1){ dp[i][0]=0; } else{ dp[i][0] = i==0?1:dp[i-1][0]; } } for (int j = 0; j <col;++j){ if (obstacleGrid[0][j] == 1){ dp[0][j] = 0; } else{ dp[0][j] = j==0?1:dp[0][j-1]; } } for (int i = 1; i < row;++i){ for (int j = 1; j<col;++j){ if (obstacleGrid[i][j] == 1){ dp[i][j] = 0; } else{ dp[i][j] = dp[i-1][j] + dp[i][j-1]; } } } return dp[row-1][col-1]; } //方法二:使用一维dp,时间复杂度O(n^2),空间复杂度O(n) int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) { int m = obstacleGrid.size(),n = obstacleGrid[0].size(); vector<int>dp(n,0); dp[0] = 1; for (int i = 0; i < m; ++i){ for (int j =0; j < n; ++j){ if (obstacleGrid[i][j]==1) dp[j]=0; else if (j>0){ dp[j] = dp[j]+dp[j-1]; } } } return dp[n-1]; }
public class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int [][] dp = new int[m][n]; dp[0][0] = 1-obstacleGrid[0][0];//初始化 for(int i=0;i<m;i++) for(int j=0;j<n;j++ ){ //该句可以避免无用功,如果是阻碍点直接丢弃,进入下一个点,同时dp[i][j]=0不影响 if(obstacleGrid[i][j]==0){ if(i==0 && j!=0) dp[0][j] = dp[0][j-1];//右赋值 else if(i!=0 && j==0) dp[i][0] = dp[i-1][0];//左赋值 else if(i!=0 && j!=0) dp[i][j]=dp[i-1][j]+dp[i][j-1];//左+上赋值 else continue; } } return dp[m-1][n-1]; } }空间换时间,重新搭建一个矩阵 ,将不能通过的地方为0,边界上的点通过后一个点根据前一个点进行 计算,其他的点则通过上,左进行计算
class Solution { public static int uniquePathsWithObstacles(int[][] obstacleGrid) { int m=obstacleGrid.length,n=obstacleGrid[0].length; int dp[][] = new int[m][n]; for(int i=0;i<m;i++){ for(int j=0;j<n;j++){ if(obstacleGrid[i][j]==1){ dp[i][j]=0; continue; } //初始化dp[0][0] if(i==0&&j==0){ dp[i][j]=1; continue; } //第一行 if(i==0){ dp[i][j]=dp[i][j-1]; continue; } //第一列 if(j==0){ dp[i][j]=dp[i-1][j]; continue; } //上述情况之外 dp[i][j]=dp[i-1][j]+dp[i][j-1]; } } return dp[m-1][n-1]; } }
int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) { int m=obstacleGrid.size(); int n=obstacleGrid[0].size(); vector<vector<int>> dp(m,vector<int>(n,0)); for(int i=0;i<m;i++){ if(obstacleGrid[i][0]!=1) dp[i][0]=1; else break; } for(int j=0;j<n;j++){ if(obstacleGrid[0][j]!=1) dp[0][j]=1; else break; } for(int i=1;i<m;i++){ for(int j=1;j<n;j++){ if(obstacleGrid[i][j]==1) dp[i][j]=0; else dp[i][j]=dp[i-1][j]+dp[i][j-1]; } } return dp[m-1][n-1]; }
class Solution { public: int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) { int n = obstacleGrid.size(); int m = obstacleGrid[0].size(); if(n==0 || m==0) return 0; vector<int> dp(m,0); dp[0] = 1; for(int i=0;i<n;i++) for(int j=0;j<m;j++) { if(obstacleGrid[i][j] == 1) dp[j] = 0; else if(j != 0) dp[j] += dp[j-1]; } return dp[m-1]; } };
class Solution { public: int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) { /* int m=obstacleGrid.size(),n=obstacleGrid[0].size(); if(obstacleGrid.empty()) return 0; int dp[m][n]; fill_n(&dp[0][0],m*n,0); dp[0][0] = obstacleGrid[0][0]==1? 0 : 1; for(int i=1;i<m;i++) dp[i][0] = obstacleGrid[i][0]==1 ? 0 : dp[i-1][0]; for(int j=1;j<n;j++) dp[0][j] = obstacleGrid[0][j]==1 ? 0 : dp[0][j-1]; for(int i=1;i<m;i++) { for(int j=1;j<n;j++) { dp[i][j] = obstacleGrid[i][j]==1 ? 0 : dp[i-1][j] + dp[i][j-1]; } } return dp[m-1][n-1]; } */ /// 使用O(n)空间的方案 int m=obstacleGrid.size(),n=obstacleGrid[0].size(); if(m==0 || n==0) return 0; vector<int> res(n,0); res[0] = 1; for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { if(obstacleGrid[i][j]==1) res[j] = 0; else if(j>0) res[j] = res[j]+res[j-1]; } } return res[n-1]; } };
package suda.alex.leetcode; public class UniquePathsWithObstacles { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int m = obstacleGrid.length; int n = obstacleGrid[0].length; int[][] dp = new int[m][n]; for (int i = 0; i < m && obstacleGrid[i][0] != 1; i++) { dp[i][0] = 1; } for (int j = 0; j < n && obstacleGrid[0][j] != 1; j++) { dp[0][j] = 1; } for (int i = 1; i < m; i++) { for (int j = 1; j < n; j++) { if(obstacleGrid[i][j] == 1){ dp[i][j] = 0; } else{ dp[i][j] = dp[i][j - 1] + dp[i - 1][j]; } } } return dp[m - 1][n - 1]; } }
public class Solution { public int uniquePathsWithObstacles(int[][] grid) { if(grid.length < 1 || grid[0].length < 1 || grid[0][0] == 1){ return 0; } int dp[] = new int[grid[0].length]; dp[0] = 1; for(int i = 1; i < grid[0].length; i++) { dp[i] = grid[0][i] == 0 ? dp[i-1] : 0; } for(int i = 1; i < grid.length; i++){ dp[0] = grid[i][0] != 1 ? dp[0] : 0; for(int j = 1; j < grid[0].length; j++) { dp[j] = grid[i][j] != 1 ? dp[j-1] + dp[j] : 0; } } return dp[grid[0].length - 1]; } }
class Solution { public: int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) { if(obstacleGrid[0][0]==1)return 0; int a=obstacleGrid.size(),b=obstacleGrid[0].size(); for(int i=0;i<a;++i) { if(obstacleGrid[i][0]==1) { for(;i<a;++i) obstacleGrid[i][0]=0; } else obstacleGrid[i][0]=1; } for(int i=1;i<b;++i) if(obstacleGrid[0][i]==1) { for(;i<b;++i) obstacleGrid[0][i]=0; } else obstacleGrid[0][i]=1; for(int i=1;i<a;++i) for(int j=1;j<b;++j) { if(obstacleGrid[i][j]==1)obstacleGrid[i][j]=0; else obstacleGrid[i][j]=obstacleGrid[i-1][j]+obstacleGrid[i][j-1]; } return obstacleGrid[a-1][b-1]; } };
public class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { if(obstacleGrid.length==0) return 0; if(obstacleGrid[0][0]==1) return 0; obstacleGrid[0][0] = 1; for(int j = 1;j<obstacleGrid[0].length;j++){ obstacleGrid[0][j] = obstacleGrid[0][j]==1?0:obstacleGrid[0][j-1]; } for(int i = 1;i<obstacleGrid.length;i++){ for(int j = 0;j<obstacleGrid[i].length;j++){ if(obstacleGrid[i][j]==1) obstacleGrid[i][j] = 0; else obstacleGrid[i][j] = (j-1>=0?obstacleGrid[i][j-1]:0)+obstacleGrid[i-1][j]; } } return obstacleGrid[obstacleGrid.length-1][obstacleGrid[0].length-1]; } }
public class Solution { public int uniquePathsWithObstacles(int[][] obstacleGrid) { int[][] dp = new int[obstacleGrid.length][obstacleGrid[0].length]; for (int i = 0; i < dp.length; i ++ ) { if(obstacleGrid[i][0] == 1) break; dp[i][0] = 1; } for (int i = 0; i < dp[0].length; i ++ ) { if(obstacleGrid[0][i] == 1) break; dp[0][i] = 1; } for (int i = 1; i < dp.length; i ++ ) { for (int j = 1; j < dp[0].length; j ++ ) { if(obstacleGrid[i][j] == 1) dp[i][j] = 0; else dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; } } return dp[dp.length - 1][dp[0].length - 1]; } }
class Solution { public: /** * * @param obstacleGrid int整型vector<vector<>> * @return int整型 */ int uniquePathsWithObstacles(vector<vector<int> >& g) { if(g.size()==0 || g[0].size()==0) return 0; // write code here int n = g.size(),m = g[0].size(); vector<vector<int> >dp(n,vector<int>(m)); for(int i=0;i<n;++i) { for(int j=0;j<m;++j) { if(i==0&& j==0) { dp[i][j] = g[i][j]==0; }else if(i==0) { if(g[i][j]==0) dp[i][j] += dp[i][j-1]; }else if(j==0) { if(g[i][j]==0) dp[i][j] +=dp[i-1][j]; }else { if(g[i][j]==0) { dp[i][j] += (dp[i-1][j]+dp[i][j-1]); } } } } return dp[n-1][m-1]; } };
int uniquePathsWithObstacles(vector<vector<int> >& obstacleGrid) { // write code here int m = obstacleGrid.size(), n = obstacleGrid[0].size(); int i, j; vector<vector<int>> graph(m, vector<int> (n,0)); for (i = 0; i < m; i++)//对行列进行处理 { if (obstacleGrid[i][0] != 1) graph[i][0] = 1; else break; } for (i = 0; i < n; i++) { if (obstacleGrid[0][i] != 1) graph[0][i] = 1; else break; } for (i = 1; i < m; i++) {//从[1][1]开始统计更新 for (j = 1; j < n; j++) { graph[i][j] = graph[i - 1][j] + graph[i][j - 1]; if (obstacleGrid[i][j] == 1) { graph[i][j] = 0; } } } return graph[m - 1][n - 1]; }
设dp[i][j]表示前i行和前j列最短路径数,状态方程如下:
i >= 2 && j >= 2
时,obstacle[i-2][j-1] != 1
, dp[i][j] += dp[i-1][j]
obstacle[i-1][j-2] != 1
, dp[i][j] += dp[i][j-1]
dp[1][k] = obstacle[0][k-1] != 1 && dp[1][k-1]!=0 ? 1 : 0
dp[k][1] = obstacle[k-1][0] != 1 && dp[k-1][1]!=0 ? 1 : 0
解释如下:
左侧非阻塞节点的最短路径数
+上侧非阻塞节点的最短路径数
代码如下:
// // Created by jt on 2020/8/30. // #include <vector> using namespace std; class Solution { public: /** * * @param obstacleGrid int整型vector<vector<>> * @return int整型 */ int uniquePathsWithObstacles(vector<vector<int> >& obstacleGrid) { // write code here if (obstacleGrid.size() < 1 || obstacleGrid[0].size() < 1) return 0; vector<vector<int> > dp(obstacleGrid.size() + 1, vector<int>(obstacleGrid[0].size() + 1, 0)); if (obstacleGrid[0][0] == 0) dp[1][1] = 1; for (int i = 2; i <= obstacleGrid.size(); ++i) { dp[i][1] = dp[i-1][1]!=0 && obstacleGrid[i-1][0]!=1 ? 1 : 0; } for (int i = 2; i <= obstacleGrid[0].size(); ++i) { dp[1][i] = dp[1][i-1]!=0 && obstacleGrid[0][i-1]!=1 ? 1 : 0; } for (int i = 2; i <= obstacleGrid.size(); ++i) { for (int j = 2; j <= obstacleGrid[0].size(); ++j) { dp[i][j] += obstacleGrid[i-2][j-1] == 0 ? dp[i-1][j] : 0; dp[i][j] += obstacleGrid[i-1][j-2] == 0 ? dp[i][j-1] : 0; } } return dp[obstacleGrid.size()][obstacleGrid[0].size()]; } };