算法设计Week12 LeetCode Algorithms Problem #63 Unique Paths II

来源:互联网 发布:如何成为游戏美工 编辑:程序博客网 时间:2024/05/17 07:02

题目描述:

Follow up for “Unique Paths”:

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
   [ [0,0,0], [0,1,0],[0,0,0] ]
The total number of unique paths is 2.


题目分析:

本题和前一题基本一致,不过多加了一个障碍物。
首先,可以容易地想到,将有障碍物的地方路径数直接清零,就可以向前文中一样不断进行累加最后得到结果了。但注意到前文中循环是从1开始的,也就是说第一行和第一列都预先置为1了。这样,如果在第一行或第一列出现障碍物,直接使用前面的循环就会无法检出障碍物。
如果使用前文中第三种方法,也就是只使用一个数组的方法,我们就可以考虑将数组长度增加1,即使用一个n+1大小的数组。将数组首先置为1,0,0, … ,0,这时,如果执行一次循环count[j] = count[j - 1] + count[j],将会得到1,1,1, … ,1。
假设第一行网格的情况为g1: 0, 0, 1, 0, 0, 0。那对应的第一行的走法就是1, 1, 0, 0, 0, 0。我们只需要在执行循环的过程中遇到障碍物时将对应的位置count设为0,就可以得到想要的效果了。
那如果第一列中出现了障碍物呢?如g2: 1, 0, 0, 0, 0, 0。如果这一行前面为g1,那对应的count数组应为:0, 1, 1, 1, 1, 1。我们不需对前面算法进行修改,就可以得到正确结果。
实现上述算法的代码如下所示,代码的时间复杂度为O(mn),空间复杂度为O(n)

class Solution {public:    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {        int m = obstacleGrid.size();        int n = m ? obstacleGrid[0].size() : 0;        vector<int> count(n, 0);        count[0] = 1;        for(int i = 0; i < m; i++){            for(int j = 0; j < n; j++){                if(obstacleGrid[i][j])                    count[j] = 0;                else if(j)                    count[j] = count[j - 1] + count[j];            }        }        return count[n - 1];    }};

其实一开始想直接修改使用count[i][j]的算法,但是过程中觉得代码并没有想象中简介,遂放弃。在LeetCode的讨论区中有一个很简洁的实现,是增加了一行一列后的算法,空间复杂度为O(mn),时间复杂度为O(mn)。在实际执行中,本算法会比前面算法略慢。现放在下面:

class Solution {public:    int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) {        int m = obstacleGrid.size() , n = obstacleGrid[0].size();        vector<vector<int>> dp(m+1,vector<int>(n+1,0));        dp[0][1] = 1;        for(int i = 1 ; i <= m ; ++i)            for(int j = 1 ; j <= n ; ++j)                if(!obstacleGrid[i-1][j-1])                    dp[i][j] = dp[i-1][j]+dp[i][j-1];        return dp[m][n];    }};

其实本题中比较巧妙的就是1,0,0, … , 0 数组的设置,这样可以很方便生成1, 1, 1, … , 1数组。

0 0