代码随想录训练营Day39 | Leetcode 62、63
一、62 不同路径
题目链接:62 不同路径
核心:当前位置只能由左边位置(向右走)或者上边位置(向下走)这两条路径得到。
第一,dp数组的定义:dp[i][j]表示从起点(0,0)到位置(i,j)的不同路径数;
第二,递推公式:dp[i][j]=dp[i-1][j]+dp[i][j-1];当前位置的不同路径数为左边和上边位置的不同路径数之和;
第三,初始化:第一行和第一列的路径都只有一条,前者是一直往右走,后者是一直往下走,故第一行和第一列的元素都初始化为1;
第四,遍历顺序,从上到下,从左到右,且从第二行第二列的第一个元素开始遍历。
注意:优化空间的处理,即只用一维数组记录不同路径数(滚动数组),统计当前行的数据时会覆盖上一行的数据,因此当前位置为当前位置(未被覆盖)和左边位置元素之和。
int uniquePaths(int m, int n) {
//动态规划
//优化空间,只用一维dp数组
vector<int> dp(n); //记录每一行的数据,下一行会覆盖上一行
for(int i=0;i<n;++i)
dp[i]=1; //第一行数据初始化为1
for(int j=1;j<m;++j)
{//从第二行开始遍历,当前位置为当前位置(上一行)和左边位置(左一列)之和
for(int i=1;i<n;++i)
dp[i]+=dp[i-1];
}
return dp[n-1];
/*
vector<vector<int>> dp(m,vector<int>(n,0)); //dp数组,记录i,j位置的路径数
for(int i=0;i<m;++i)
dp[i][0]=1; //第一列位置的路径只有一条,即往下走
for(int j=0;j<n;++j)
dp[0][j]=1; //第一行位置的路径只有一条,即往右走
for(int i=1;i<m;++i)
{//从i=1和j=1开始从左往右从上到下依次统计dp数组
for(int j=1;j<n;++j)
dp[i][j]=dp[i-1][j]+dp[i][j-1]; //当前位置可由上一次的左边往右走或者上边往下走
}
return dp[m-1][n-1];
*/
}
二、63 不同路径II
题目链接:63 不同路径II
核心:当前位置只能从左边位置或上边位置得到,且不存在障碍物,因为一旦遇到障碍物表示这条路径不通,即令当前位置元素为0.
第一,dp数组的定义:dp[i][j]记录当前位置(i,j)的不同路径数;
第二,递归公式:依然是dp[i][j]=dp[i-1][j]+dp[i][j-1],但存在条件,即不存在障碍物,如果遇到障碍物则令其为0(由于最初定义dp数组时就令所有元素为0,因此遍历时遇到障碍物直接continue,无需处理该位置的元素值。)
第三,初始化:第一行和第一列且不存在障碍物的位置均初始化为1,存在障碍物的位置依然为0;
第四,遍历顺序:从上到下,从左到右依次遍历。
(起点或终点存在障碍物都直接返回0,表示不存在可通的路径)
注意:优化空间的处理,不仅在遍历时对障碍物进行处理,而在初始化第一行元素时也需要对障碍物进行处理,即在第一行中如果遇到障碍物则令其为0,未遇到障碍物时,第一个位置则初始化为1,其他位置不是直接初始化为1,而是继承相邻左边位置的元素值(因为可能相邻左边是障碍物)。
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
//动态规划,遇到障碍需赋值为0,或者无需更新当前位置(因初始化已经为0)
//优化空间
int m=obstacleGrid.size(); //row
int n=obstacleGrid[0].size(); //col
if(obstacleGrid[0][0]==1 || obstacleGrid[m-1][n-1]==1)
return 0; //起点或终点有障碍物,则不存在路径
vector<int> dp(n,0); //一维数组,记录每一行数据,下一行覆盖上一行
for(int j=0;j<n; ++j)
{//第一行初始化:遇到障碍物令其为0,以及障碍物之后的位置都为0
if(obstacleGrid[0][j]==1)
dp[j]=0;
else if(j==0)
dp[j]=1; //没有障碍物且第一个位置
else
dp[j]=dp[j-1]; //没有障碍物除了第一个位置,继承上一个位置的值
}
for(int i=1;i<m;++i)
{//从第二行开始遍历
for(int j=0;j<n;++j)
{//从第二列的第一个位置开始,因为第一个位置可能有障碍物,不能默认为1
if(obstacleGrid[i][j]==1)
dp[j]=0; //遇到障碍物则令其为0
else if(j!=0)
dp[j]+=dp[j-1]; //没有障碍物且不是第一个位置
}
}
return dp[n-1];
/*
int m=obstacleGrid.size(); //row
int n=obstacleGrid[0].size(); //col
if(obstacleGrid[0][0]==1 || obstacleGrid[m-1][n-1]==1)
return 0; //起点或终点有障碍物,则不存在路径
vector<vector<int>> dp(m,vector<int>(n,0)); //dp数组初始化为0
//初始化第一行和第一列dp数组时需考虑障碍情况
for(int i=0;i<m && obstacleGrid[i][0]==0;++i)
dp[i][0]=1;
for(int j=0;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)
continue; //遇到障碍则跳过此位置,无需更新,即该位置仍为0
dp[i][j]=dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
*/
}