题目概述
链接:点我做题
题解
动态规划及其优化
本题的关键是状态转移方程,定义
f
(
i
,
j
)
f(i,j)
f(i,j)为坐标(0,0)到坐标(i,j)的不同路径数目,由于只能往下走或者往右走,往下走一步后剩余路径相当于坐标
(
0
,
0
)
(0,0)
(0,0)到坐标
(
i
−
1
,
j
)
(i-1,j)
(i−1,j),往右走一步后剩余路径相当于坐标
(
0
,
0
)
(0,0)
(0,0)到坐标
(
i
,
j
−
1
)
(i,j-1)
(i,j−1),再考虑上阻碍的问题,状态转移方程为:
f
(
i
,
j
)
=
f
(
i
−
1
,
j
)
+
f
(
i
,
j
−
1
)
,
i
f
(
o
b
s
t
a
c
l
e
G
r
i
d
(
i
,
j
)
!
=
0
)
f
(
i
,
j
)
=
0
,
e
l
s
e
初
始
条
件
f
(
0
,
0
)
=
(
o
b
s
t
a
c
l
e
G
r
i
d
(
0
,
0
)
=
=
0
)
f
(
0
,
i
)
=
(
o
b
s
t
a
c
l
e
G
r
i
d
(
0
,
0
)
=
=
0
)
&
&
(
o
b
s
t
a
c
l
e
G
r
i
d
(
0
,
1
)
=
=
0
)
&
&
.
.
.
&
&
(
o
b
s
t
a
c
l
e
G
r
i
d
(
0
,
i
−
1
)
=
=
0
)
f(i,j)=f(i-1,j)+f(i,j-1),if(obstacleGrid(i,j)!=0)\\ f(i,j)=0,else\\ 初始条件\\ f(0,0)=(obstacleGrid(0,0)==0)\\ f(0,i)=(obstacleGrid(0,0)==0)\&\&(obstacleGrid(0,1)==0)\\\&\&...\&\&(obstacleGrid(0,i-1)==0)\\
f(i,j)=f(i−1,j)+f(i,j−1),if(obstacleGrid(i,j)!=0)f(i,j)=0,else初始条件f(0,0)=(obstacleGrid(0,0)==0)f(0,i)=(obstacleGrid(0,0)==0)&&(obstacleGrid(0,1)==0)&&...&&(obstacleGrid(0,i−1)==0)
观察到假如外层遍历i,内层遍历j时,求j的值只与上一轮i循环求得
f
(
i
−
1
,
j
)
f(i-1,j)
f(i−1,j)的值和这一轮遍历j是上一次求得值
f
(
i
,
j
−
1
)
f(i,j-1)
f(i,j−1)有关,所以可以直接用一个一维数组储存上一轮外层遍历计算的j的状态。
并且发现这个数组的元素个数等于内层循环遍历的次数,所以可以比较m和n的大小,如果m小就让m在内层遍历,如果n小就让n在内层遍历:
class Solution {
public:
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid)
{
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
int ret;
if (n < m)
{
vector<int> dp(n);
dp[0] = (obstacleGrid[0][0] == 0);
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
if (obstacleGrid[i][j] == 1)
{
dp[j] = 0;
}
else
{
dp[j] = dp[j] + (j - 1 >= 0 ?
dp[j - 1] : 0);
}
}
}
ret = dp.back();
}
else
{
vector<int> dp(m);
dp[0] = (obstacleGrid[0][0] == 0);
for (int i = 0; i < n; ++i)
{
for (int j = 0; j < m; ++j)
{
if (obstacleGrid[j][i] == 1)
{
dp[j] = 0;
}
else
{
dp[j] = dp[j] +
(j - 1 >= 0 ? dp[j - 1] : 0);
}
}
}
ret = dp.back();
}
return ret;
}
};
时间复杂度;
O
(
m
∗
n
)
O(m*n)
O(m∗n)
空间复杂度:
O
(
m
i
n
(
m
,
n
)
)
O(min(m,n))
O(min(m,n))