Leet Code题解 - 1559. Detect Cycles in 2D Grid 检测二维无向图中的环
Leet Code题解 —— 1559. Detect Cycles in 2D Grid 检测二维无向图中的环
- 前言
- 一、题目描述
- 二、思路整理
- 1. 审题
- 2. 分布实现步骤
- 2.1 将二维数组处理为连通图
- 2.2 判断连通图中是否有环
- 三、实现样例
前言
找找感觉,记录一下个人解题思路系列。记录一下力扣里面的经典题目的个人想法。
一、题目描述
https://leetcode.com/problems/detect-cycles-in-2d-grid/
在二维无向图中检测环。如果有多个环,只要判断任意一个。
给定一个m*n的二维字符数组,请找出该数组中,是否存在由相同值构成的环。
一个环应该是一个长度不少于4的路径,该路径的起点和终点都在同一格内。
对任意给定格子来说,我们只能移动到其相邻格(仅限上、下、左、右四个方向,不包括斜角方向),同时,该相邻格应具有同当前格相同的值。
同时,你不能移动到你上一次曾移动过的各自中,例如:(1, 1) -> (1, 2) -> (1,1)不属于有效的环,因为对于(1, 2)来说,(1, 1)是上次访问过的格。
若存在相同值构成的环,则返回true,否则返回false。
1. 例一
输入: grid = [[“a”,“a”,“a”,“a”],[“a”,“b”,“b”,“a”],[“a”,“b”,“b”,“a”],[“a”,“a”,“a”,“a”]]
输出: true
解释: 如下图,有两个环。
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 == grid[i].length
1 <= m <= 500
1 <= n <= 500
格内仅包含小写字母。
二、思路整理
1. 审题
可以看到,给的判断函数的原型是:bool containsCycle(vector<vector>& grid) {}
其中,输入的可以看做是一个二维的数组,数组内填充的是小写字母。
输出要求的只是判断是否存在环的结果。
一般环的判断,我们是基于联通图来做的。所以,这个二维的数组我们先需要把它转为连通图。那么整题的步骤分为:
- 将二维数组处理为连通图
- 判断连通图中是否有环
2. 分布实现步骤
2.1 将二维数组处理为连通图
由于原数组是二维数组,为了简化我们的处理逻辑,我们可以将二维的图处理为一维图。
我们可以采用一维链表来存储,并根据原图内数据(字母)处理其连通性,若:
m == grid.length
n == grid[i].length
i, j为原二维数组下标
新一维数组下标 index = i * n + j;
如下图,原表示为:
vector<vector> grid1 =
{
{'a','a','a','a'},{'a','b','b','a'},{'a','b','b','a'},{'a','a','a','a'}};
处理后的连通图为
0 : 1, 4;
1 : 0, 2;
2 : 1, 3;
3 : 2, 7;
4 : 0, 8;
5 : 9, 6;
6 : 5, 10;
7 : 3, 11;
8 : 4, 12;
9 : 5, 10;
10 : 6, 9;
11 : 7, 15;
12 : 8, 13;
13 : 12, 14;
14 : 13, 15;
15 : 11, 14;
2.2 判断连通图中是否有环
得到连通图后,本题即转换为基于一个无向图判断有环的问题。
判断图中的环,我们可以采用 DFS,深度优先检索来判断是否有环。
深度优先的通常写法是递归型的,即对现有的节点进行判断,并遍历其子节点,然后依次对子节点进行深度优先搜索。
遍历上述连通图,在遍历的过程中,我们只需判断某节点是否有一条边指向已访问过的节点,如果有,则表示存在环。但需注意:
- 判断已访问过的节点,不应该是当前节点的父节点(无向图两个节点间是互相可联通的,但这种父子节点间的连通性不被认为是环);
- 一个节点有三种状态,因此我们的判断应该是,遍历过程中如果发现某节点存在一条边指向非父节点的已被访问的灰色节点,则存在环;
- 已遍历完全(该节点所有的路径(或子节点)均已被遍历) —— 黑色
- 已被访问但未遍历完全 —— 灰色
- 未被访问 —— 白色
- 由于遍历是递归的,因此在某一次的子递归函数中存在环,则需要向上传递该判定结果
三、实现样例
class Solution {private:bool dfs(vector<vector<int>> &connected_graph, int &start_node){bool has_cycle = false;// flag the node has been visitedreached[start_node] = 1;for (auto child : connected_graph[start_node]) {if (reached[child] == 1 && child != parent_node[start_node]) {has_cycle = true;break;}else if (reached[child] == 0) {parent_node[child] = start_node;// pass the has_cycle result to upper layerhas_cycle = dfs(connected_graph, child);if (has_cycle == true){break;}}}// all the path is visitedreached[start_node] = 2;return has_cycle;}// represent the all the nodes can be reached to this nodevector<int> reached;vector<int> parent_node;public:bool containsCycle(vector<vector<char>>& grid) {vector<vector<int>> connected_graph;/******************************************//* Step 1. initialize the connected graph *//******************************************/connected_graph.resize(grid.size()*grid[0].size());reached.resize(grid.size()*grid[0].size());parent_node.resize(grid.size()*grid[0].size());for(auto var : parent_node){var = grid.size()*grid[0].size();}int i = 0; int j = 0;for(i=0; i<grid.size(); i++){for(j=0; j<grid[0].size(); j++){// calculator how many ways each block can accessif(i>0){if(grid[i][j] == grid[i-1][j]){connected_graph[i*grid[0].size()+j].push_back((i-1)*grid[0].size()+j);}}if(j>0){if(grid[i][j] == grid[i][j-1]){connected_graph[i*grid[0].size()+j].push_back(i*grid[0].size()+j-1);}}if(i<grid.size()-1){if(grid[i][j] == grid[i+1][j]){connected_graph[i*grid[0].size()+j].push_back((i+1)*grid[0].size()+j);}}if(j<grid[0].size()-1){if(grid[i][j] == grid[i][j+1]){connected_graph[i*grid[0].size()+j].push_back(i*grid[0].size()+j+1);}}}}/******************************************//* Step 2. judge there has cycle *//******************************************/bool has_cycle = false;for (int k = 0; k < reached.size(); k++){/* begin the dfs search beginning node */if(reached[k] == 0){// bfs search from node-khas_cycle = dfs(connected_graph, k);}else{continue;}if(has_cycle == true){return true;}}return has_cycle; }
};
Leet Code题解 - 1559. Detect Cycles in 2D Grid 检测二维无向图中的环相关推荐
- TP5使用二维码PHP QR Code生成带LOGO和不带LOGO的二维码
TP5使用二维码PHP QR Code生成带LOGO和不带LOGO的二维码 1.下载二维码插件Phpqrcode,地址 https://sourceforge.net/projects/phpqrco ...
- 【剑指offer题解】二维数组中的查找
前言 众所周知,对于面试而言,<剑指offer>是一本"好书". 如果你和我一样是个算法菜鸡,那么最推荐的是先把剑指offer的题目搞明白,其次再去刷LeetCode等 ...
- leetcode 304. Range Sum Query 2D - Immutable |304. 二维区域和检索 - 矩阵不可变(二维前缀和问题)
题目 https://leetcode.com/problems/range-sum-query-2d-immutable/ 题解 本题是 medium 难度,二维前缀和问题.相似题目有: Easy: ...
- 2D shape decompositions二维形状分解
论文阅读:The 2D Shape Structure Dataset: A User Annotated Open Access Database 以下约定几个变量: parts:即shape 分解 ...
- 【Android QR Code】开源项目:ZXing(三)二维码解码
继续上一节的内容 本节我们将对上一节的QQ群号二维码进行解码 QQ群号二维码图片另存为后,将下载的.jpg拷贝到项目assets目录下 1.解码配置 Map<DecodeHintType,Obj ...
- Leet Code OJ 223. Rectangle Area [Difficulty: Easy]
题目: Find the total area covered by two rectilinear rectangles in a 2D plane. Each rectangle is defin ...
- 2d 蓝图_“二渲三”打破传统思维!Netflix冲奥动画会推动2D动画变革吗?
我们看到了Netflix做原创动画的野心,二维动画的高度将被重新定义. 编辑 | Katei Netflix的第一部原创动画电影<克劳斯:圣诞节的秘密>将冲击奥斯卡最佳动画长片!这也是Ne ...
- Python+OpenCV:二维直方图(2D Histograms)
Python+OpenCV:二维直方图(2D Histograms) ################################################################# ...
- 二维码(QR code)基本结构及生成原理
什么是二维码 二维码 (2-dimensional bar code),是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的. 在许多种类的二维条码中,常用的码制 ...
最新文章
- 在简历中应用STAR法则
- Java中传值与传地址
- c语言变长数组_2018级C语言大作业 - 祖玛
- BZOJ4557:[JLOI2016/SHOI2016]侦察守卫——题解
- 微软的云笔记:OneNote+SkyDrive
- UITextField加间隔符号格式化
- 从scheduler is shutted down看程序员的英文水平
- ostream作为函数返回值_函数的调用(一)
- c++中delete和析构函数之间的区别
- 桌面下雪软件测试工程师,桌面下雪
- Win8.1激活方法
- linux系统 浏览器安装包下载,Linux版360浏览器安装包非常大的原因
- 【英特尔杯】Python调取萤石网络摄像头视频
- 【超图】SuperMap iClient3D 11i for WebGL新产品食用指南(一)
- 上帝或许不掷骰子,但可能会踢足球|图片中的数学之美
- 【Java】interrupt、interrupted和isInterrupted的区别
- SpringMVC_初级总结
- Lombok的@Data注解自动重写equals
- 04 修改数据库用户密码
- 几张一模一样的照片_一个人持有两个真实的身份证 照片看上去一模一样
热门文章
- 单片微型计算机简称单片机是指集成,什么是单片微型计算机 -解决方案-华强电子网...
- php 声波图,Canvas 美丽的声波图
- sql注入pythonpoco_.NET EF(Entity Framework)详解
- 光纤收发器的原理及应用_光纤收发器的几种常规应用
- 安卓下载保存到本地(二)
- Android ListView下拉刷新、上拉载入更多
- presto spill to disk
- configure: error: Cannot find php-config. Please use --with-php-config=PATH
- 算法4------字符串的字典序最长子序列
- Docker镜像的多平台架构支持