每日一道leetcode(2026.04.27):检查网格中是否存在有效路径

每日一道leetcode(2026.04.27):检查网格中是否存在有效路径

  • [1. 题目](#1. 题目)
  • [2. 分析](#2. 分析)
  • [3. 代码实现](#3. 代码实现)
  • [4. 总结](#4. 总结)

1. 题目

给你一个 m x n 的网格 grid。网格里的每个单元都代表一条街道。grid[i][j] 的街道可以是:

1 表示连接左单元格和右单元格的街道。

2 表示连接上单元格和下单元格的街道。

3 表示连接左单元格和下单元格的街道。

4 表示连接右单元格和下单元格的街道。

5 表示连接左单元格和上单元格的街道。

6 表示连接右单元格和上单元格的街道。

你最开始从左上角的单元格 (0,0) 开始出发,网格中的「有效路径」是指从左上方的单元格 (0,0) 开始、一直到右下方的 (m-1,n-1) 结束的路径。该路径必须只沿着街道走。

注意:你不能变更街道。 如果网格中存在有效的路径,则返回 true,否则返回 false 。

示例 1:

输入:grid = [[2,4,3],[6,5,2]]

输出:true

解释:如图所示,你可以从 (0, 0) 开始,访问网格中的所有单元格并到达 (m - 1, n - 1) 。

示例 2:

输入:grid = [[1,2,1],[1,2,1]]

输出:false

解释:如图所示,单元格 (0, 0)上的街道没有与任何其他单元格上的街道相连,你只会停在 (0, 0) 处。

示例 3:

输入:grid = [[1,1,2]]

输出:false

解释:你会停在 (0, 1),而且无法到达 (0, 2) 。

示例 4:

输入:grid = [[1,1,1,1,1,1,3]]

输出:true

示例 5:

输入:grid = [[2],[2],[2],[2],[2],[2],[6]]

输出:true

提示:

m == grid.length

n == grid[i].length

1 <= m, n <= 300

1 <= grid[i][j] <= 6

2. 分析

这道题主要考察的是思路,而非性能。每种街道类型其实对应两种走法,比如Street1,虽然是从左到右的一条直道,但也可以是从右到左的走法,你很能想到测试用例里面一定有这种弯弯绕绕的路线等着咱们。

另一点需要注意的是,虽然起点是(0,0),但并不需要起点的入口是上方或者是左方,可以是任一一方,那么,从起点开始,就需要判断这个单元格的两个街道方向,是否有可能走到目的终点。下图的测试用例即为实际需要返回为true的案例。

基于这些分析,我的思路是把所有街道类型的走法给穷举出来,然后从起点开始,按照这个街道的两个通道方向往下找,主要计算下一个单元格的位置,判断是否超出界限,是否连通即可。

3. 代码实现

java 复制代码
class Solution {
    // 入口和出口的朝向 0-up 1-right 2-down 3-left
    // 入口是当前单元格的入口,出口则是下一个单元格的入口
    private static final int[][][] path = new int[][][]{
            {{1, 1}, {3, 3}},
            {{0, 0}, {2, 2}},
            {{1, 0}, {2, 3}},
            {{2, 1}, {3, 0}},
            {{1, 2}, {0, 3}},
            {{0, 1}, {3, 2}}
    };

    private static final int[][][] next = new int[][][]{
            {{0, 1}, {0, -1}},
            {{1, 0}, {-1, 0}},
            {{1, 0}, {0, -1}},
            {{0, 1}, {1, 0}},
            {{-1, 0}, {0, -1}},
            {{0, 1}, {-1, 0}}
    };

    public boolean hasValidPath(int[][] grid) {
        if (grid.length == 1 && grid[0].length == 1) {
            return true;
        }
        int index = grid[0][0] - 1;
        // 首个位置需特殊处理
        int[][] firstPath = path[index];
        // 方向1
        int[][] nextCord = next[index];
        if (find(grid, nextCord[0][0], nextCord[0][1], firstPath[0][1])) {
            return true;
        }
        // 方向2
        return find(grid, nextCord[1][0], nextCord[1][1], firstPath[1][1]);
    }

    private static boolean find(int[][] grid, int x, int y, int lastDirection) {
        while (true) {
            // 是否走出边界外
            if (x < 0 || x >= grid.length || y < 0 || y >= grid[0].length) {
                return false;
            }
            int index = grid[x][y] - 1;
            boolean flag;
            int[][] ints = path[index];
            if (x == 0 && y == 0) {
                // 又回到了起点
                return false;
            }
            // 判断连通性
            if (ints[0][0] == lastDirection) {
                flag = true;
            } else if (ints[1][0] == lastDirection) {
                flag = false;
            } else {
                // 道路不通
                return false;
            }
            if (x == grid.length - 1 && y == grid[0].length - 1) {
                // 走到终点
                return true;
            }
            // 获取下一个位置
            int[] cord = next[index][flag ? 0 : 1];
            x += cord[0];
            y += cord[1];
            // 当前位置的出口方向
            lastDirection = flag ? ints[0][1] : ints[1][1];
        }
    }
}

4. 总结

补充说明一下path,通过三维数组定义每种街道的两种通道类型。

以这个Street3为例,如果是左上角进入,那么这个单元格的入口类型为1,对应的出口类型为2,但是,在判断连通性的时候,是用当前的出口与下个单元格的入口类型进行匹配,所以,此处我直接将这个出口类型2转换为了入口类型0,所以(1,0)是这么来的。换个放下,若成下方进,则入口类型为2,出口类型为1,再将出口类型转换为下个单元格的入口类型3,所以有了(2,3)。完整地,Street3的path数据即为{``{1, 0}, {2, 3}}

相关推荐
我不是懒洋洋2 小时前
【数据结构】二叉树链式结构的实现(二叉树的遍历、使用二叉树的基本方法、二叉树的创建和销毁)
c语言·数据结构·c++·经验分享·算法·链表·visual studio
水木流年追梦2 小时前
CodeTop Top 300 热门题目8-字符串解码
linux·运维·服务器·前端·算法·leetcode
lcj25112 小时前
精选5大高频链表与数组算法详解:从旋转数组到链表公共节点,LeetCode实战代码+图解全解析
算法·leetcode·链表
xin_nai2 小时前
LeetCode热题100(Java)(4)子串
java·算法·leetcode
一只数据集2 小时前
机器学习多领域综合数据集分析-包含基因表达时间序列分类回归数据-适用于算法训练模型评估科研应用
人工智能·算法·数据分析
c++之路2 小时前
C++ 命名空间(Namespace)
开发语言·c++·算法
jiang_bluetooth3 小时前
奈奎斯特第一准则理解和WIFI OFDM的关联
算法
DuHz10 小时前
论文精读:大语言模型 (Large Language Models, LLM) —— 一项调查
论文阅读·人工智能·深度学习·算法·机器学习·计算机视觉·语言模型
檀越剑指大厂11 小时前
32 万星的面试学习计划 + 内网穿透工具,程序员面试准备效率翻倍!
学习·面试·职场和发展