A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).

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.

Note: m and n will be at most 100.

Example 1:

Input:
[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]
Output: 2
Explanation:
There is one obstacle in the middle of the 3x3 grid above.
There are two ways to reach the bottom-right corner:
1. Right -> Right -> Down -> Down
2. Down -> Down -> Right -> Right

这道题是之前那道 Unique Paths 的延伸,在路径中加了一些障碍物,还是用动态规划 Dynamic Programming 来解,使用一个二维的 dp 数组,大小为 (m+1) x (n+1),这里的 dp[i][j] 表示到达 (i-1, j-1) 位置的不同路径的数量,那么i和j需要更新的范围就是 [1, m] 和 [1, n]。状态转移方程跟之前那道题是一样的,因为每个位置只能由其上面和左面的位置移动而来,所以也是由其上面和左边的 dp 值相加来更新当前的 dp 值,如下所示:

dp[i][j] = dp[i-1][j] + dp[i][j-1]

这里就能看出来初始化 d p数组的大小为 (m+1) x (n+1),是为了 handle 边缘情况,当i或j为0时,减1可能会出错。当某个位置是障碍物时,其 dp 值为0,直接跳过该位置即可。这里还需要初始化 dp 数组的某个值,使得其能正常累加。当起点不是障碍物时,其 dp 值应该为1,即dp[1][1] = 1,由于其是由 dp[0][1] + dp[1][0] 更新而来,所以二者中任意一个初始化为1即可。由于之后 LeetCode 更新了这道题的 test case,使得使用 int 型的 dp 数组会有溢出的错误,所以改为使用 long 型的数组来避免 overflow,代码如下:

解法一:

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

或者我们也可以使用一维 dp 数组来解,省一些空间,参见代码如下:

解法二:

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

Github 同步地址:

https://github.com/grandyang/leetcode/issues/63

类似题目:

Unique Paths

Unique Paths III

参考资料:

https://leetcode.com/problems/unique-paths-ii/

https://leetcode.com/problems/unique-paths-ii/discuss/23250/Short-JAVA-solution

https://leetcode.com/problems/unique-paths-ii/discuss/23248/My-C%2B%2B-Dp-solution-very-simple!

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 63. Unique Paths II 不同的路径之二的更多相关文章

  1. LeetCode 63. Unique Paths II不同路径 II (C++/Java)

    题目: A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). ...

  2. [LeetCode] Unique Paths II 不同的路径之二

    Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...

  3. leetcode 63. Unique Paths II

    Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...

  4. LeetCode: 63. Unique Paths II(Medium)

    1. 原题链接 https://leetcode.com/problems/unique-paths-ii/description/

  5. [leetcode] 63. Unique Paths II (medium)

    原题 思路: 用到dp的思想,到row,col点路径数量 : path[row][col]=path[row][col-1]+path[row-1][col]; 遍历row*col,如果map[row ...

  6. leetcode 62. Unique Paths 、63. Unique Paths II

    62. Unique Paths class Solution { public: int uniquePaths(int m, int n) { || n <= ) ; vector<v ...

  7. 【LeetCode】63. Unique Paths II

    Unique Paths II Follow up for "Unique Paths": Now consider if some obstacles are added to ...

  8. [Leetcode Week12]Unique Paths II

    Unique Paths II 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/unique-paths-ii/description/ Descrip ...

  9. 62. Unique Paths && 63 Unique Paths II

    https://leetcode.com/problems/unique-paths/ 这道题,不利用动态规划基本上规模变大会运行超时,下面自己写得这段代码,直接暴力破解,只能应付小规模的情形,当23 ...

随机推荐

  1. docker安装和配置Grafana

    目录 安装 docker 启动 配置 配置域名和端口 配置ldap 配置邮箱 添加数据源 创建dashboard 配置alert 安装 docker 启动 先普通启动,然后把配置文件导出来,修改配置文 ...

  2. NoNodeAvailableException[None of the configured nodes are available:[.127.0.0.1}{127.0.0.1:9300]

    我在springboot 集成 elasticsearch,启动springboot测试创建索引,建立索引的时候报 : NoNodeAvailableException[None of the con ...

  3. Solr集群(即SolrCloud)搭建与使用

    1.什么是SolrCloud SolrCloud(solr 云)是Solr提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud.当一个系统的索引数据量少的时候是不 ...

  4. JZOJ.2117. 【2016-12-30普及组模拟】台风

    题目大意: 天气预报频道每天从卫星上接受卫星云图.图片被看作是一个矩阵,每个位置上要么是”#”,要么”.”,”#”表示该位置没有云,”.”表示有云,地图上每个位置有多达8个相邻位置,分别是,左上.上. ...

  5. Java获取客户端真实IP地址

    Java代码 import javax.servlet.http.HttpServletRequest; /** * 获取对象的IP地址等信息 */ public class IPUtil { /** ...

  6. 一次压测中tomcat生成session释放不及时导致的频繁fullgc性能优化案例

    性能问题:老年代一直处于占满状态,为什么没有发生内存溢出 以HotSpot VM的分代式GC为例,普通对象分配都是在young gen进行的,具体是从在位于young gen中的eden space中 ...

  7. Eclipse 笔记

    2004年前的开发架构:(操作系统+数据库+中间件+开发工具) AIX + DB2 + WAS + WSAD  ===  皇家级 UNIX/Linux + Oracle +BEA WebLogic + ...

  8. python 的三元操作符

    条件表达式(三元操作符)    1.有了这个三元操作符的条件表达式,你可以使用一条语句来完成下面的条件判断和赋值操作: x,y=4,5 if x<y: temp = x else: temp = ...

  9. 【Idea】idea中编译后无法提示错误信息的解决方案

  10. 8、RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较

    RabbitMQ三种Exchange模式(fanout,direct,topic)的性能比较 RabbitMQ中,除了Simple Queue和Work Queue之外的所有生产者提交的消息都由Exc ...