每日一道leetcode(2026.04.29):二维网格图中探测环

每日一道leetcode(2026.04.29):二维网格图中探测环

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

1. 题目

给你一个二维字符网格数组 grid ,大小为 m x n ,你需要检查 grid 中是否存在 相同值 形成的环。

一个环是一条开始和结束于同一个格子的长度 大于等于4的路径。对于一个给定的格子,你可以移动到它上、下、左、右四个方向相邻的格子之一,可以移动的前提是这两个格子有 相同的值 。

同时,你也不能回到上一次移动时所在的格子。比方说,环 (1, 1) -> (1, 2) -> (1, 1) 是不合法的,因为从 (1,2) 移动到 (1, 1) 回到了上一次移动时的格子。

如果 grid 中有相同值形成的环,请你返回 true ,否则返回 false 。

示例 1:

输入:grid = \["a","a","a","a","a","b","b","a","a","b","b","a","a","a","a","a"]

输出:true

解释:如下图所示,有 2 个用不同颜色标出来的环:

示例 2:

输入:grid = \["c","c","c","a","c","d","c","c","c","c","e","c","f","c","c","c"]

输出:true

解释:如下图所示,只有高亮所示的一个合法环:

示例 3:

输入:grid = \["a","b","b","b","z","b","b","b","a"]

输出:false

提示:

m == grid.length

n == gridi.length

1 <= m <= 500

1 <= n <= 500

grid只包含小写英文字母。

2. 分析

这道题是比较dfs的典型题型,以基础单元格,分别向上下左右四个方向去找,首先要保证延伸的单元格的值要一样,然后就是移动的步数,避免a→b→a这种假环形的误判,同时还要避免对已经搜索过的单元格进行多次搜索,不然就极可能死循环。

3. 代码实现

java 复制代码
class Solution {
    public boolean containsCycle(char[][] grid) {
        int[][] stepRecord = new int[grid.length][grid[0].length];
        // 从0,0开始判断是否有环形存在
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (grid[i][j] == '0') {
                    continue;
                }
                char c = grid[i][j];
                if (dfs(grid, c, i, j, stepRecord, 1)) {
                    return true;
                }
            }
        }
        return false;
    }

    private static boolean dfs(char[][] grid, char c, int i, int j, int[][] stepRecord, int step) {
        if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length) {
            // 判断是否超出边界
            return false;
        }
        // 判断是否回到之前的点,并且步数大于2
        if (stepRecord[i][j] != 0 && step > 1) {
            // 回到起点形成环形
            return Math.abs(stepRecord[i][j] - step) >= 4;
        }
        if (grid[i][j] != c || grid[i][j] == '0') {
            // 字符不匹配或已经遍历过
            return false;
        }
        // 标记
        grid[i][j] = '0';
        stepRecord[i][j] = step;
        // 向下、向上、向右、向左搜索
        boolean res = dfs(grid, c, i + 1, j, stepRecord, step + 1) ||
                dfs(grid, c, i - 1, j, stepRecord, step + 1) ||
                dfs(grid, c, i, j + 1, stepRecord, step + 1) ||
                dfs(grid, c, i, j - 1, stepRecord, step + 1);
        // 将步数标记还原为0,避免重新定义和初始化导致的超时
        stepRecord[i][j] = 0;
        return res;
    }
}

4. 总结

后面有必要对dfs和bfs的解题思路和典型题型进行一次总结了。

一开始我使用的是map来记录移动的步数,最终也能不超时通过,击败大概5%左右,就想着使用二维数组来替换map,但是反而超时了。超时原因主要是初始化的耗时,如果是grid的行和列比较大时,对于初始化map的耗时是一样的,map的耗时主要是后续key多了之后,hash以及链表查询的耗时较高;而如果是循环内每次都重新初始化一个二维数组,那么这个耗时就是杠杠的高,即使许多元素用不到。所以想着使用一个全局的二维数组,但又会出现数据污染,前面的遍历修改的值,对后面的遍历可能有影响,所以需要对数据进行清除。

另外,需要注意的一点,以基础单元格gridij为原点进行查找环形的时候,最后找到的环形可能用不到这个单元格,即环形不包含gridij,搜索的终点不是gridij

相关推荐
qeen872 小时前
【数据结构】自平衡二叉搜索树各种旋转算法原理解析及AVL树的C++实现
数据结构·c++·算法
lucas_AI2 小时前
1.2B 小模型赢过 235B 大模型:NaviDC-OCR 把文档解析卷明白了
人工智能·深度学习·算法
冻柠檬飞冰走茶3 小时前
PTA基础编程题目集 7-35有理数均值(C++语言实现)
开发语言·数据结构·c++·算法·均值算法
民乐团扒谱机3 小时前
【微实验】倒谱算法(Cepstrum)深度解析:原理、数学推导与代码实现
人工智能·算法·语音识别
evans在进步3 小时前
LeetCode 394:字符串解码——Java 单栈模拟与嵌套解析详解
java·python·leetcode
Nil2084 小时前
leetcode 189轮转数组
数据结构·算法·leetcode
-dzk-4 小时前
【动态规划】LC 118.杨辉三角
算法·动态规划
恣逍信点4 小时前
《凌微经》静态自悖——变化之自因
人工智能·科技·算法·机器学习·业界资讯·拓扑学·哲学
ychqsq4 小时前
115.整理
经验分享·职场和发展
吃着火锅x唱着歌4 小时前
LeetCode 3885.设计事件管理器
算法·leetcode·职场和发展