信物传送
难度:
标签:
题目描述
English description is not available for the problem. Please switch to Chinese.
代码结果
运行时间: 41 ms, 内存: 16.3 MB
/*
* 思路:使用广度优先搜索(BFS)找到从起点到终点的最短路径。每次改变一个传送带的方向并检查是否能更接近终点。
*
* 实现步骤:
* 1. 初始化队列和访问标记。
* 2. 使用队列进行BFS,记录每次改变传送带方向后的状态。
* 3. 找到最少的操作次数,使得信物从起点到达终点。
*/
import java.util.*;
import java.util.stream.IntStream;
public class SolutionStream {
private static final int[][] directions = { {0, 1}, {1, 0}, {0, -1}, {-1, 0} };
private static final char[] symbols = {'>', 'v', '<', '^'};
public int minMagicOperations(String[] matrix, int[] start, int[] end) {
int rows = matrix.length;
int cols = matrix[0].length();
boolean[][][] visited = new boolean[rows][cols][4];
Queue<int[]> queue = new LinkedList<>();
queue.add(new int[]{start[0], start[1], 0});
visited[start[0]][start[1]][0] = true;
int operations = 0;
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
int[] current = queue.poll();
int r = current[0];
int c = current[1];
int dir = current[2];
if (r == end[0] && c == end[1]) {
return operations;
}
IntStream.range(0, 4).forEach(j -> {
int newR = r + directions[j][0];
int newC = c + directions[j][1];
if (isValid(matrix, newR, newC, rows, cols) && !visited[newR][newC][j]) {
visited[newR][newC][j] = true;
queue.add(new int[]{newR, newC, j});
}
});
}
operations++;
}
return -1; // 无法到达终点
}
private boolean isValid(String[] matrix, int r, int c, int rows, int cols) {
return r >= 0 && r < rows && c >= 0 && c < cols;
}
}
解释
方法:
该题解采用了广度优先搜索(BFS)的思路。首先,创建一个与矩阵相同大小的访问数组 vst,用于记录每个位置是否被访问过。然后,从起点 start 开始,按照传送带的方向移动,并将到达的新位置加入到队列中。每次移动后,检查是否到达终点 end,如果到达,则返回当前的施法次数 c。如果没有到达,则对当前位置的四个方向进行探索,如果相邻的位置没有被访问过,则将其加入到下一轮的队列中,并更新访问数组。每一轮探索结束后,施法次数 c 加一。如果最终无法到达终点,则返回 -1。
时间复杂度:
O(m * n)
空间复杂度:
O(m * n)
代码细节讲解
🦆
如何处理在边界位置时传送带方向可能会指向矩阵外的情况?例如,如果在矩阵的最右侧一列,传送带方向向右,该如何确保不会引发索引错误?
▷🦆
在该题解中,对每个位置的四个方向进行探索时,所使用的条件`if i and not vst[i - 1][j]`似乎没有完全考虑边界条件,是否应该更明确地检查边界?
▷🦆
为什么在到达终点后就直接返回当前的施法次数,而不考虑当前队列中可能还存在其他未探索的路径可能需要更少的施法次数?
▷