迷路的机器人
难度:
标签:
题目描述
Imagine a robot sitting on the upper left corner of grid with r rows and c columns. The robot can only move in two directions, right and down, but certain cells are "off limits" such that the robot cannot step on them. Design an algorithm to find a path for the robot from the top left to the bottom right.
"off limits" and empty grid are represented by 1
and 0
respectively.
Return a valid path, consisting of row number and column number of grids in the path.
Example 1:
Input: [ [0,0,0], [0,1,0], [0,0,0] ] Output: [[0,0],[0,1],[0,2],[1,2],[2,2]]
Note:
r, c <= 100
代码结果
运行时间: 23 ms, 内存: 16.6 MB
/*
题目思路:
使用深度优先搜索(DFS)来寻找从左上角到右下角的路径。首先,我们需要检查当前网格是否有效(即在边界内并且不是障碍物)。
然后我们尝试向下或向右移动。如果我们找到了一个有效的路径,我们返回这条路径。
如果当前路径不通,则回溯并尝试另一条路径。
使用Java Stream的递归特性和Optional类来处理路径查找和回溯。
*/
import java.util.*;
import java.util.stream.*;
public class RobotPathStream {
public List<int[]> findPath(int[][] grid) {
return findPath(grid, 0, 0).orElse(new ArrayList<>());
}
private Optional<List<int[]>> findPath(int[][] grid, int row, int col) {
// 检查边界和障碍物
if (row < 0 || col < 0 || row >= grid.length || col >= grid[0].length || grid[row][col] == 1) {
return Optional.empty();
}
List<int[]> path = new ArrayList<>();
path.add(new int[]{row, col});
// 如果到达右下角,返回路径
if (row == grid.length - 1 && col == grid[0].length - 1) {
return Optional.of(path);
}
// 标记当前路径
grid[row][col] = 1;
// 尝试向下或向右移动
Optional<List<int[]>> downPath = findPath(grid, row + 1, col);
Optional<List<int[]>> rightPath = findPath(grid, row, col + 1);
// 合并路径
Optional<List<int[]>> resultPath = Stream.of(downPath, rightPath)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
// 回溯
grid[row][col] = 0;
if (resultPath.isPresent()) {
path.addAll(resultPath.get());
return Optional.of(path);
}
return Optional.empty();
}
public static void main(String[] args) {
RobotPathStream rps = new RobotPathStream();
int[][] grid = {
{0, 0, 0},
{0, 1, 0},
{0, 0, 0}
};
List<int[]> path = rps.findPath(grid);
path.forEach(p -> System.out.println(Arrays.toString(p)));
}
}
解释
方法:
这个题解首先判断右下角是否有障碍,如果有,则直接返回空路径。若没有障碍,从右下角开始,逆向考虑每个位置是否可以到达。使用标记值2代表可以向下走到达终点,标记值3代表可以向右走到达终点。这个标记过程是一个逆向的动态规划过程。开始于右下角,向左上角逆推,每个格子根据其右侧和下方的格子的标记来确定自己的标记。最后,如果左上角的格子被标记为可行(标记值大于1),则构造路径。路径的构造是根据每个格子的标记决定下一步是向下还是向右移动。
时间复杂度:
O(r*c)
空间复杂度:
O(r*c)
代码细节讲解
🦆
在题解中,为什么先检查右下角是否有障碍物,而不是从左上角开始检查?
▷🦆
题解中提到使用标记值2和3来表示可以向下或向右行走,如果一个格子同时可以向下和向右行走怎样处理?
▷🦆
在反向标记过程中,对于边缘的格子(如最左列或最上行),题解如何确保不会访问到网格之外的元素?
▷