490. The Maze

Posted optor

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了490. The Maze相关的知识,希望对你有一定的参考价值。

原题链接:https://leetcode.com/articles/the-maze/
这道题目是需要冲会员才能使用的,然而我个穷逼现在还是失业状态根本冲不起。。。以后如果把免费题目都刷完了的话,再来冲会员刷这些题目吧!

我的思路

迷宫类问题首先想到的就是回溯法了,思考+实现用了近 3 个小时,终于又写出了简单粗暴的实现来了:

import java.util.Stack;

/**
 * Created by clearbug on 2018/2/26.
 */
public class Solution {

    public static void main(String[] args) {
        Solution s = new Solution();
        /**
         * 0 0 1 0 0
         0 0 0 0 0
         0 0 0 1 0
         1 1 0 1 1
         0 0 0 0 0
         */
        int[][] board = {
                {0, 0, 1, 0, 0},
                {0, 0, 0, 0, 0},
                {0, 0, 0, 1, 0},
                {1, 1, 0, 1, 1},
                {0, 0, 0, 0, 0},
        };
        System.out.println(s.traverse(board, 0, 4, 4, 4));

        /**
         * 0 0 1 0 0
         0 0 0 0 0
         0 0 0 1 0
         1 1 0 1 1
         0 0 0 0 0

         */
        int[][] board2 = {
                {0, 0, 1, 0, 0},
                {0, 0, 0, 0, 0},
                {0, 0, 0, 1, 0},
                {1, 1, 0, 1, 1},
                {0, 0, 0, 0, 0},
        };
        System.out.println(s.traverse(board2, 0, 4, 3, 2));
    }

    public Stack<String> traverse(int[][] board, int rowStart, int colStart, int rowDest, int colDest) {
        board[rowStart][colStart] = -1; // 标记起始位置已来过

        Stack<String> res = new Stack<>();
        boolean dfsRes = dfs(board, rowStart, colStart, rowDest, colDest, res);
        System.out.println(dfsRes);
        return res;
    }

    public boolean dfs(int[][] board, int rowStart, int colStart, int rowDest, int colDest, Stack<String> res) {
        if (rowStart == rowDest && colStart == colDest) { // 说明已抵达目的地
            return true;
        }

        boolean exist = false;

        // up
        int upRow = rowStart - 1;
        while (upRow >= 0 && board[upRow][colStart] < 1) { // board[upRow][colStart] = 0 or board[upRow][colStart] = -1
            exist = true;
            upRow--;
        }
        if (exist) {
            upRow++;
            res.push("up");
            if (upRow == rowDest && colStart == colDest) { // 说明已抵达目的地
                return true;
            }
            if (board[upRow][colStart] == -1) { // 说明来过这个位置,目前又循环回来了,所以是死路
                res.pop();
            } else {
                board[upRow][colStart] = -1; // 标记这个位置已来过
                if (dfs(board, upRow, colStart, rowDest, colDest, res)) {
                    return true;
                } else {
                    res.pop();
                }
            }
        }


        exist = false;
        // down
        int downRow = rowStart + 1;
        while (downRow < board.length && board[downRow][colStart] < 1) { // board[downRow][colStart] = 0 or board[downRow][colStart] = -1
            exist = true;
            downRow++;
        }
        if (exist) {
            downRow--;
            res.push("down");
            if (downRow == rowDest && colStart == colDest) { // 说明已抵达目的地
                return true;
            }
            if (board[downRow][colStart] == -1) { // 说明来过这个位置,目前又循环回来了,所以是死路
                res.pop();
            } else {
                board[downRow][colStart] = -1; // 标记这个位置已来过
                if (dfs(board, downRow, colStart, rowDest, colDest, res)) {
                    return true;
                } else {
                    res.pop();
                }
            }
        }

        exist = false;
        // left
        int leftCol = colStart - 1;
        while (leftCol >= 0 && board[rowStart][leftCol] < 1) {
            exist = true;
            leftCol--;
        }
        if (exist) {
            leftCol++;
            res.push("left");
            if (rowStart == rowDest && leftCol == colDest) {
                return true;
            }
            if (board[rowStart][leftCol] == -1) {
                res.pop();
            } else {
                board[rowStart][leftCol] = -1;
                if (dfs(board, rowStart, leftCol, rowDest, colDest, res)) {
                    return true;
                } else {
                    res.pop();
                }
            }
        }

        exist = false;
        // right
        int rightCol = colStart + 1;
        while (rightCol < board[rowStart].length && board[rowStart][rightCol] < 1) {
            exist = true;
            rightCol++;
        }
        if (exist) {
            rightCol--;
            res.push("right");
            if (rowStart == rowDest && rightCol == colDest) {
                return true;
            }
            if (board[rowStart][rightCol] == -1) {
                res.pop();
            } else {
                board[rowStart][rightCol] = -1;
                if (dfs(board, rowStart, rightCol, rowDest, colDest, res)) {
                    return true;
                } else {
                    res.pop();
                }
            }
        }

        return false;
    }


}

当然了,可以使用类似骑士游历问题中的预测算法来提高效率。下面就来看看官方解答是怎么的吧!

官方方法一(深入优先搜索)

深度优先搜索,英文全称为 Depth First Search,简称为 DFS。毫无疑问,跟我的思路是一样的,就是代码更加简洁,所以我的解法其实就是深度优先搜索啦!

官方解法二(广度优先搜索)

广度优先搜索,英文全称 Breadth First Search,简称 BFS。不过我思考了下,这种广度优先搜索算法最终是无法求出小球所走过的路径的,只能判断小球最终是否会到达目的地。还是按照惯例抄袭一遍代码就当学会了吧:

import java.util.LinkedList;
import java.util.Stack;
import java.util.Queue;

/**
 * Created by clearbug on 2018/2/26.
 */
public class Solution {

    public static void main(String[] args) {
        Solution s = new Solution();
        /**
         * 0 0 1 0 0
         0 0 0 0 0
         0 0 0 1 0
         1 1 0 1 1
         0 0 0 0 0
         */
        int[][] board = {
                {0, 0, 1, 0, 0},
                {0, 0, 0, 0, 0},
                {0, 0, 0, 1, 0},
                {1, 1, 0, 1, 1},
                {0, 0, 0, 0, 0},
        };
        System.out.println(s.hasPath(board, new int[]{0, 4}, new int[]{4, 4}));

        /**
         * 0 0 1 0 0
         0 0 0 0 0
         0 0 0 1 0
         1 1 0 1 1
         0 0 0 0 0

         */
        int[][] board2 = {
                {0, 0, 1, 0, 0},
                {0, 0, 0, 0, 0},
                {0, 0, 0, 1, 0},
                {1, 1, 0, 1, 1},
                {0, 0, 0, 0, 0},
        };
        System.out.println(s.hasPath(board2, new int[]{0, 4}, new int[]{3, 2}));
    }

    public boolean hasPath(int[][] maze, int[] start, int[] dest) {
        boolean[][] visited = new boolean[maze.length][maze[0].length];
        visited[start[0]][start[1]] = true;

        int[][] dirs = {
                {0, 1},
                {0, -1},
                {-1, 0},
                {1, 0}
        };

        Queue<int[]> queue = new LinkedList<>();
        queue.add(start);

        while (!queue.isEmpty()) {
            int[] s = queue.remove();
            if (s[0] == dest[0] && s[1] == dest[1]) {
                return true;
            }
            for (int[] dir : dirs) {
                int x = s[0] + dir[0];
                int y = s[1] + dir[1];
                while (x >= 0 && y >= 0 && x < maze.length && y < maze[0].length && maze[x][y] == 0) {
                    x += dir[0];
                    y += dir[1];
                }
                if (!visited[x - dir[0]][y - dir[1]]) {
                    queue.add(new int[]{x - dir[0], y - dir[1]});
                    visited[x - dir[0]][y - dir[1]] = true;
                }
            }
        }

        return false;
    }

}

以上是关于490. The Maze的主要内容,如果未能解决你的问题,请参考以下文章

[LC] 490. The Maze

LeetCode 499. The Maze III

The Maze

The Maze II

505. The Maze II

505. The Maze II