class Solution {
public:
int minimumObstacles(vector<vector<int>>& grid) {
}
};
2290. 到达角落需要移除障碍物的最小数目
给你一个下标从 0 开始的二维整数数组 grid
,数组大小为 m x n
。每个单元格都是两个值之一:
0
表示一个 空 单元格,1
表示一个可以移除的 障碍物 。你可以向上、下、左、右移动,从一个空单元格移动到另一个空单元格。
现在你需要从左上角 (0, 0)
移动到右下角 (m - 1, n - 1)
,返回需要移除的障碍物的 最小 数目。
示例 1:
输入:grid = [[0,1,1],[1,1,0],[1,1,0]] 输出:2 解释:可以移除位于 (0, 1) 和 (0, 2) 的障碍物来创建从 (0, 0) 到 (2, 2) 的路径。 可以证明我们至少需要移除两个障碍物,所以返回 2 。 注意,可能存在其他方式来移除 2 个障碍物,创建出可行的路径。
示例 2:
输入:grid = [[0,1,0,0,0],[0,1,0,1,0],[0,0,0,1,0]] 输出:0 解释:不移除任何障碍物就能从 (0, 0) 到 (2, 4) ,所以返回 0 。
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 105
2 <= m * n <= 105
grid[i][j]
为 0
或 1
grid[0][0] == grid[m - 1][n - 1] == 0
原站题解
golang 解法, 执行用时: 216 ms, 内存消耗: 23.4 MB, 提交时间: 2023-09-26 20:00:09
type pair struct{ x, y int } var dir4 = []struct{ x, y int }{{-1, 0}, {1, 0}, {0, -1}, {0, 1}} func minimumObstacles(grid [][]int) (ans int) { m, n := len(grid), len(grid[0]) dis := make([][]int, m) for i := range dis { dis[i] = make([]int, n) for j := range dis[i] { dis[i][j] = m * n } } dis[0][0] = 0 q := [2][]pair{{{}}} // 两个 slice 头对头来实现 deque for len(q[0]) > 0 || len(q[1]) > 0 { var p pair if len(q[0]) > 0 { p, q[0] = q[0][len(q[0])-1], q[0][:len(q[0])-1] } else { p, q[1] = q[1][0], q[1][1:] } for _, d := range dir4 { x, y := p.x+d.x, p.y+d.y if 0 <= x && x < m && 0 <= y && y < n { g := grid[x][y] if dis[p.x][p.y]+g < dis[x][y] { dis[x][y] = dis[p.x][p.y] + g q[g] = append(q[g], pair{x, y}) } } } } return dis[m-1][n-1] }
cpp 解法, 执行用时: 312 ms, 内存消耗: 100.5 MB, 提交时间: 2023-09-26 19:59:56
class Solution { static constexpr int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; public: int minimumObstacles(vector<vector<int>> &grid) { int m = grid.size(), n = grid[0].size(); int dis[m][n]; memset(dis, 0x3f, sizeof(dis)); dis[0][0] = 0; deque<pair<int, int>> q; q.emplace_front(0, 0); while (!q.empty()) { auto [x, y] = q.front(); q.pop_front(); for (auto &[dx, dy] : dirs) { int nx = x + dx, ny = y + dy; if (0 <= nx && nx < m && 0 <= ny && ny < n) { int g = grid[nx][ny]; if (dis[x][y] + g < dis[nx][ny]) { dis[nx][ny] = dis[x][y] + g; g == 0 ? q.emplace_front(nx, ny) : q.emplace_back(nx, ny); } } } } return dis[m - 1][n - 1]; } };
java 解法, 执行用时: 54 ms, 内存消耗: 72.7 MB, 提交时间: 2023-09-26 19:59:43
class Solution { static final int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; public int minimumObstacles(int[][] grid) { int m = grid.length, n = grid[0].length; var dis = new int[m][n]; for (var i = 0; i < m; i++) Arrays.fill(dis[i], Integer.MAX_VALUE); dis[0][0] = 0; var q = new ArrayDeque<int[]>(); q.addFirst(new int[]{0, 0}); while (!q.isEmpty()) { var p = q.pollFirst(); int x = p[0], y = p[1]; for (var d : dirs) { int nx = x + d[0], ny = y + d[1]; if (0 <= nx && nx < m && 0 <= ny && ny < n) { var g = grid[nx][ny]; if (dis[x][y] + g < dis[nx][ny]) { dis[nx][ny] = dis[x][y] + g; if (g == 0) q.addFirst(new int[]{nx, ny}); else q.addLast(new int[]{nx, ny}); } } } } return dis[m - 1][n - 1]; } }
python3 解法, 执行用时: 1756 ms, 内存消耗: 41.3 MB, 提交时间: 2023-09-26 19:59:32
''' 0-1 bfs 把障碍物当作可以经过的单元格,经过它的代价为 1,空单元格经过的代价为 0。 问题转化成从起点到终点的最短路。 ''' class Solution: def minimumObstacles(self, grid: List[List[int]]) -> int: m, n = len(grid), len(grid[0]) dis = [[inf] * n for _ in range(m)] dis[0][0] = 0 q = deque([(0, 0)]) while q: x, y = q.popleft() for nx, ny in (x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1): if 0 <= nx < m and 0 <= ny < n: g = grid[x][y] if dis[x][y] + g < dis[nx][ny]: dis[nx][ny] = dis[x][y] + g if g == 0: q.appendleft((nx, ny)) else: q.append((nx, ny)) return dis[m - 1][n - 1]