题目1
62. 不同路径【中等】
题解
动态规划
明白是二维动态规划之后就好做了
状态转移方程:dp[i][j]=dp[i][j-1]+dp[i-1][j];
class Solution {
public int uniquePaths(int m, int n) {
int dp[][]=new int[m][n];
for(int i=0;i<m;i++)
dp[i][0]=1;
for(int j=1;j<n;j++)
dp[0][j]=1;
for(int i=1;i<m;i++){
for(int j=1;j<n;j++){
dp[i][j]=dp[i][j-1]+dp[i-1][j];
}
}
return dp[m-1][n-1];
}
}
时间复杂度:
O
(
m
n
)
O(mn)
O(mn)
空间复杂度:
O
(
m
n
)
O(mn)
O(mn),注意到dp[i][j]仅与第 i 行和第 i-1 行的状态有关,因此我们可以使用滚动数组代替代码中的二维数组,使空间复杂度降低为 O(n)。
组合数学
用组合数学的方法也能做,向下走有
m
?
1
m-1
m?1次,向右走有
n
?
1
n-1
n?1次,所以一共
m
+
n
?
2
m+n-2
m+n?2次移动,我们要从这
m
+
n
?
2
m+n-2
m+n?2次移动中选择
m
?
1
m-1
m?1个向下移动,所以公式为
class Solution {
public int uniquePaths(int m, int n) {
long res=1;
for(int i=0;i<m-1;i++){
res=res*(n+i)/(i+1);
}
return (int)res;
}
}
时间复杂度:
O
(
m
)
O(m)
O(m)
空间复杂度:
O
(
1
)
O(1)
O(1)
题目2
63. 不同路径 II【中等】
题解
比上一题多了一个障碍物,有障碍物的地方到达不了dp[i][j]=0
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m=obstacleGrid.length,n=obstacleGrid[0].length;
if(obstacleGrid[0][0]==1||obstacleGrid[m-1][n-1]==1)
return 0;
int dp[][]=new int[m][n];
for(int i=0;i<m && obstacleGrid[i][0]==0;i++)
dp[i][0]=1;
for(int j=1;j<n && obstacleGrid[0][j]==0;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];
}
}
时间复杂度:
O
(
m
n
)
O(mn)
O(mn)
空间复杂度:
O
(
m
n
)
O(mn)
O(mn)
优化 滚动数组优化空间复杂度
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m=obstacleGrid.length,n=obstacleGrid[0].length;
int dp[]=new int[n];
for(int j=0;j<n && obstacleGrid[0][j]==0;j++)
dp[j]=1;
for(int i=1;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-1]+dp[j];
}
}
return dp[n-1];
}
}
时间复杂度:
O
(
m
n
)
O(mn)
O(mn)
空间复杂度:
O
(
n
)
O(n)
O(n)
|