leetcode- 检查网格中是否存在有效路径

 题目是LeetCode第181场周赛的第三题,链接: 检查网格中是否存在有效路径。具体描述较长,详情请点击前面链接。

 其实蛮明显的这就是一道DFS的题目,所以可以从原点(0,0)出发,递归地访问各单元格,看能否到达终点。这里需要注意的是两个单元格能连接的条件,就是一个单元格到另一单元格的延展方向(比如向右)必须在另一个单元格中有匹配的方向(比如向左)。

 我自己写的一个比较繁琐的JAVA版代码可见我的Github

 上面没放代码是因为各种if-else太多,代码长度太长了,然后现在开始思考怎么使得代码更简洁。可以给方向赋值,比如上-0,右-1,下-2,左-3。然后可以发现一个规律,那就是下一个单元格的匹配方向nextDir跟当前单元格的向外延展方向currentDir之间有个关系: ( n e x t D i r + 2 ) % 4 = = c u r r e n t D i r (nextDir+2)\%4==currentDir 。然后对于每个方向,我们也可以提前用数组保存该方向会导致的坐标移动,比如右方向会导致(1,0)的坐标变动。而且也可以不用递归了,只要有方向可以走,就一直往下走(当然需要避免有环的存在导致死循环,所以需要记录访问过的单元格),用循环即可完成。

class Solution {
    // 表示各个方向的x, y坐标变化值
    private final int[][] DIRECTIONS = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    //TOP - 0, RIGHT - 1, BOTTOM - 2, LEFT - 3
    private final int[][] STREETS = {{-1, -1}, {1, 3}, {0, 2}, {2, 3}, {1, 2}, {0, 3}, {0, 1}};
    
    public boolean hasValidPath(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;
        if (m == 1 && n == 1) {
            return true;
        }
        //从0,0处出发
        for (int direction : STREETS[grid[0][0]]) {
            if (direction == 1 || direction == 2) {
                boolean[][] visited = new boolean[m][n];
                int i = 0, j = 0;
                int currentDir = direction;
                while (true) {
                    //避免有环的存在造成死循环
                    if (visited[i][j]) {
                        break;
                    }
                    visited[i][j] = true;
                    //下一个单元格的位置
                    i += DIRECTIONS[currentDir][0];
                    j += DIRECTIONS[currentDir][1];
                    if (i < 0 || j < 0 || i >= m || j >= n) {
                        break;
                    }
                    int nextDir1 = STREETS[grid[i][j]][0], nextDir2 = STREETS[grid[i][j]][1];
                    //下一个单元格的某一个方向能与当前单元格向外延展方向匹配,那么下一个向外延展方向就是另一个方向
                    if ((nextDir1 + 2) % 4 == currentDir) {
                        currentDir = nextDir2;
                    }
                    else if ((nextDir2 + 2) % 4 == currentDir) {
                        currentDir = nextDir1;
                    }
                    else {
                        break;
                    }
                    if (i == m - 1 && j == n - 1) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}

 提交结果如下:


 Python版代码如下:

class Solution:
    def hasValidPath(self, grid: List[List[int]]) -> bool:
        DIRECTIONS = [[-1, 0], [0, 1], [1, 0], [0, -1]]
        STREETS = [[-1, -1], [1, 3], [0, 2], [2, 3], [1, 2], [0, 3], [0, 1]]
        m = len(grid)
        n = len(grid[0])
        if m == 1 and n == 1:
            return True
        for direction in STREETS[grid[0][0]]:
            if direction == 1 or direction == 2:
                visited = [[False for _ in range(n)] for _ in range(m)]
                currentDir = direction
                i, j = 0, 0
                while True:
                    if visited[i][j]:
                        break
                    visited[i][j] = True
                    i += DIRECTIONS[currentDir][0]
                    j += DIRECTIONS[currentDir][1]
                    if i < 0 or j < 0 or i >= m or j >= n:
                        break
                    nextDir1, nextDir2 = STREETS[grid[i][j]][0], STREETS[grid[i][j]][1]
                    if (nextDir1 + 2) % 4 == currentDir:
                        currentDir = nextDir2
                    elif (nextDir2 + 2) % 4 == currentDir:
                        currentDir = nextDir1
                    else:
                        break
                    if i == m - 1 and j == n - 1:
                        return True
        return False

 提交结果如下:


发布了68 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/JR_Chan/article/details/105144215