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

题目描述:

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值