每天一道LeetCode-----计算从二维数组的左上角到达右下角的所有路径数及最短的那条,如果存在障碍物时又是多少
Unique Paths
原题链接Unique Paths
计算从左上角有多少条不同的路径可以到达右下角,移动方向只能是向右和向下。
对于每个位置,都有两种移动的可能,即向右移动和向下移动。可以用深度优先(dfs)解决,同时为了解决重复计算,可以用动态规划的思想,记录从dp[i][j]到达右下角有多少条不同的路径。
除了深度优先之外,可以用迭代法执行动态规划,这样做可以减少dp的维度,只需要一维数组即可,不过要改变dp的含义,假设当前所在位置为(m, n),那么dp[n]代表从左上角到达当前位置的不同路径书,原因为
- 移动方向只能向右和向下,所以只要向下移动一行,就不能再返回上一行。这说明,对于行的记录是可以忽略的。
- 只要遍历每一行的每一列,不断更新dp[n]直到到达右下角即可,假设当前在第m行的第n列,那么dp[n]表示从左上角开始移动可以有多少条不同的路径达到第m行第n列
- 对于每个位置,它可以从上一行的当前列向下移动到达当前位置,也可以从当前行的上一列向右移动到达当前位置
- 所以dp[n] = dp[n] + dp[n - 1],dp[n]代表从上一行的第n列到达右下角的不同路径数,dp[n - 1]代表从当前行的第n-1列到达右下角的不同路径数
- 直到遍历到右下角,即遍历了所有行所有列,那么dp[n]就代表从左上角到达右下角的不同路径数
代码如下
class Solution { public:int uniquePaths(int m, int n) {/* 到达第0行,第j列的路径数只有1条 */vector<int> dp(n, 1);/* 这里直接忽略了第0行和第0列,原因是到达第0行和第0列的某个位置的路径都只有1条 */for(int i = 1; i < m; ++i){for(int j = 1; j < n; ++j){/* dp[j]表示从左上角到达第i行第j列的不同路径数 *//* 当i为m-1,j为n-1时,就是从左上角到达右下角的不同路径数 */dp[j] = dp[j] + dp[j - 1];}}return dp[n - 1];} };Unique Paths II
原题链接Unique Paths II
接着上面的问题,如果某些位置有障碍物,那么有多少条路径可以到达右下角。
移动的过程中不能到达障碍物所在的位置。
方法和上面一样,仍然有一维数组记录到达某一列的不同路径,不过需要判断某个位置是否有障碍物,如果有,那么dp[n]为0,否则dp[n] = dp[n - 1] + dp[n]
另外,对于dp[0]要特殊处理,不能像上面一样直接从第一行第一列开始,因为第0行第0列都可能存在障碍物导致dp[n[不是1而是0.
代码如下
class Solution { public:int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {if(obstacleGrid.empty())return 0;int m = obstacleGrid.size();int n = obstacleGrid[0].size();/* 如果起始位置和目标位置都有障碍物,那么就不可能到达 */if(n == 0 || obstacleGrid[0][0] == 1 || obstacleGrid[m-1][n-1] == 1)return 0;vector<int> dp(n);/* 到达开始位置的路径为1 */dp[0] = 1;/* 到达第0行的某个位置的路径,有障碍物的话后面就都是0,否则是1 */for(int i = 1; i < n; ++i)dp[i] = (obstacleGrid[0][i] == 1) ? 0 : dp[i - 1];for(int i = 1; i < m; ++i){/* 如果当前行的第0列是障碍物,那么到达当前行的第0列的路径数为0 */if(obstacleGrid[i][0] == 1)dp[0] = 0;for(int j = 1; j < n; ++j){dp[j] = obstacleGrid[i][j] == 1 ? 0 : dp[j] + dp[j - 1];}}return dp[n - 1];} };原题链接Minimum Path Sum
和上面的题一样,只是这回要求是找到路径长度最短的那一条,路径长度是路径上所有数字的和
仍然采用迭代法的动态规划,不过要改变dp的含义,即dp[n]表示从左上角到达当前位置的最小路径长,而不在是不同路径数
另外,第一行和第一列不再单纯的是1,而是数字累加,代表路径长
代码如下
上面三道题主要利用动态规划的思想,另外通过迭代法简化动态规划数组的维度。
总结
以上是生活随笔为你收集整理的每天一道LeetCode-----计算从二维数组的左上角到达右下角的所有路径数及最短的那条,如果存在障碍物时又是多少的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 每天一道LeetCode-----将数组
- 下一篇: 每天一道LeetCode-----将用数