leetcode
leetcode 2901 ~ 2950
变换的迷宫

变换的迷宫

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 510 ms, 内存: 43.6 MB


/*
 * 思路:
 * 使用Java Stream API重写同样的逻辑。
 */
import java.util.*;
import java.util.stream.Collectors;

public class MazeSolverStream {
    private static final int[] directions = {-1, 0, 1, 0, -1};

    public boolean canEscape(String[][] maze) {
        int T = maze.length;
        int N = maze[0].length;
        int M = maze[0][0].length();
        boolean[][][] visited = new boolean[T][N][M];
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[]{0, 0, 0});
        visited[0][0][0] = true;

        while (!queue.isEmpty()) {
            List<int[]> currentLevel = queue.stream().collect(Collectors.toList());
            queue.clear();

            for (int[] current : currentLevel) {
                int t = current[0], x = current[1], y = current[2];

                if (x == N - 1 && y == M - 1) {
                    return true;
                }

                for (int i = 0; i < 4; i++) {
                    int nx = x + directions[i];
                    int ny = y + directions[i + 1];
                    int nt = t + 1;
                    if (nx >= 0 && ny >= 0 && nx < N && ny < M && nt < T && !visited[nt][nx][ny] && maze[nt].charAt(nx) == '.') {
                        visited[nt][nx][ny] = true;
                        queue.add(new int[]{nt, nx, ny});
                    }
                }
            }
        }

        return false;
    }
}

解释

方法:

题解采用了深度优先搜索(DFS)结合记忆化的方法来解决问题。首先,函数通过递归尝试所有可能的路径来探索迷宫。每个递归调用尝试从当前位置(x, y)在当前时间(dep)向四个方向以及原地(共五种可能)移动,并考虑是否使用两种魔法卷轴。记忆化通过Python的装饰器lru_cache实现,这可以避免重复计算已经探索过的状态。剪枝操作包括检查是否可能在剩余的时间内到达终点,即通过简单的距离和时间比较来快速剪除不可能的路径。如果能在迷宫变化结束前到达终点,则返回true,否则在所有可能都尝试后返回false。

时间复杂度:

O(n * m * max_dep)

空间复杂度:

O(n * m * max_dep)

代码细节讲解

🦆
为什么题解中选择使用深度优先搜索(DFS)而不是广度优先搜索(BFS)来解决这个问题?
在解决路径搜索问题时,DFS和BFS各有优势。DFS的优点在于其空间复杂度通常比BFS低,因为DFS只需存储单条路径上的节点,而BFS需要存储整个层级的节点。对于变换的迷宫这种需要探索多种状态(位置,时间,和魔法使用情况)的问题,DFS能更有效地探索深层状态,尤其当配合剪枝和记忆化时,能快速排除无效路径。此外,DFS在找到一条有效路径时可以立即终止整个搜索,这对于此类问题是一个明显的优势。
🦆
在使用记忆化搜索时,lru_cache的参数为什么设置为None,这样的设置有什么特别的意义或好处吗?
在Python中使用lru_cache装饰器时,参数None意味着缓存的大小(即可以存储多少个不同的调用结果)是无限的。这在递归深度优先搜索中非常有用,因为可能会有大量的不同状态需要缓存,从而避免重复计算。无限的缓存尺寸确保了所有可能的状态都被记忆,这对于提高算法的效率是非常有帮助的,特别是在有大量可能状态的问题中。
🦆
题解提到了剪枝操作,具体是如何判断`n - 1 - x + m - 1 - y > max_dep - dep - 1`这一条件的,能否详细解释其逻辑依据?
此剪枝条件基于最简单的距离和时间的估算。`n - 1 - x + m - 1 - y`计算的是从当前位置(x, y)到目标位置(n-1, m-1)的曼哈顿距离,即最少需要的步数。`max_dep - dep - 1`计算的是从当前时间点(dep)到迷宫变化停止的时间(max_dep)之前,还可以进行的最大移动次数。如果所需的最少步数超过了剩余可移动的次数,那么无论如何都不可能在迷宫变化完成前到达终点,因此这条路径可以被剪枝,即直接判断为不可能成功的路径,从而节省搜索时间。

相关问题