给你一个二维字符网格数组 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 == grid[i].length
1 <= m <= 500
1 <= n <= 500
grid
只包含小写英文字母。
构造并查集,遍历每个坐标 (i, j)
,如果下方或者右侧的元素 (x, y)
与当前元素 (i, j)
相同,进行合并操作。若是,若此前两个坐标已经处于连通状态,再进行合并时会形成环,直接返回 true。否则遍历结束返回 false。
并查集模板:
模板 1——朴素并查集:
# 初始化,p存储每个点的父节点
p = list(range(n))
# 返回x的祖宗节点
def find(x):
if p[x] != x:
# 路径压缩
p[x] = find(p[x])
return p[x]
# 合并a和b所在的两个集合
p[find(a)] = find(b)
模板 2——维护 size 的并查集:
# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量
p = list(range(n))
size = [1] * n
# 返回x的祖宗节点
def find(x):
if p[x] != x:
# 路径压缩
p[x] = find(p[x])
return p[x]
# 合并a和b所在的两个集合
if find(a) != find(b):
size[find(b)] += size[find(a)]
p[find(a)] = find(b)
模板 3——维护到祖宗节点距离的并查集:
# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离
p = list(range(n))
d = [0] * n
# 返回x的祖宗节点
def find(x):
if p[x] != x:
t = find(p[x])
d[x] += d[p[x]]
p[x] = t
return p[x]
# 合并a和b所在的两个集合
p[find(a)] = find(b)
d[find(a)] = distance
class Solution:
def containsCycle(self, grid: List[List[str]]) -> bool:
def find(x):
if p[x] != x:
p[x] = find(p[x])
return p[x]
m, n = len(grid), len(grid[0])
p = list(range(m * n))
for i in range(m):
for j in range(n):
for a, b in [[0, 1], [1, 0]]:
x, y = i + a, j + b
if x < m and y < n and grid[x][y] == grid[i][j]:
if find(x * n + y) == find(i * n + j):
return True
p[find(x * n + y)] = find(i * n + j)
return False
class Solution {
private int[] p;
public boolean containsCycle(char[][] grid) {
int m = grid.length;
int n = grid[0].length;
p = new int[m * n];
for (int i = 0; i < p.length; ++i) {
p[i] = i;
}
int[] dirs = {0, 1, 0};
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < 2; ++k) {
int x = i + dirs[k];
int y = j + dirs[k + 1];
if (x < m && y < n && grid[i][j] == grid[x][y]) {
if (find(x * n + y) == find(i * n + j)) {
return true;
}
p[find(x * n + y)] = find(i * n + j);
}
}
}
}
return false;
}
private int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
}
class Solution {
public:
vector<int> p;
bool containsCycle(vector<vector<char>>& grid) {
int m = grid.size(), n = grid[0].size();
p.resize(m * n);
for (int i = 0; i < p.size(); ++i) p[i] = i;
vector<int> dirs = {0, 1, 0};
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
for (int k = 0; k < 2; ++k) {
int x = i + dirs[k], y = j + dirs[k + 1];
if (x < m && y < n && grid[x][y] == grid[i][j]) {
if (find(x * n + y) == find(i * n + j)) return 1;
p[find(x * n + y)] = find(i * n + j);
}
}
}
}
return 0;
}
int find(int x) {
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
};
func containsCycle(grid [][]byte) bool {
m, n := len(grid), len(grid[0])
p := make([]int, m*n)
for i := range p {
p[i] = i
}
var find func(x int) int
find = func(x int) int {
if p[x] != x {
p[x] = find(p[x])
}
return p[x]
}
dirs := []int{1, 0, 1}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
for k := 0; k < 2; k++ {
x, y := i+dirs[k], j+dirs[k+1]
if x < m && y < n && grid[x][y] == grid[i][j] {
if find(x*n+y) == find(i*n+j) {
return true
}
p[find(x*n+y)] = find(i*n + j)
}
}
}
}
return false
}
/**
* @param {character[][]} grid
* @return {boolean}
*/
var containsCycle = function (grid) {
const m = grid.length;
const n = grid[0].length;
let p = Array.from({ length: m * n }, (_, i) => i);
function find(x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
const dirs = [0, 1, 0];
for (let i = 0; i < m; ++i) {
for (let j = 0; j < n; ++j) {
for (let k = 0; k < 2; ++k) {
const x = i + dirs[k];
const y = j + dirs[k + 1];
if (x < m && y < n && grid[x][y] == grid[i][j]) {
if (find(x * n + y) == find(i * n + j)) {
return true;
}
p[find(x * n + y)] = find(i * n + j);
}
}
}
}
return false;
};