diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/README.md b/solution/1500-1599/1559.Detect Cycles in 2D Grid/README.md index 80fa17cbdd788..e5049e8db2967 100644 --- a/solution/1500-1599/1559.Detect Cycles in 2D Grid/README.md +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/README.md @@ -78,7 +78,11 @@ tags: -### 方法一 +### 方法一:BFS + +我们可以遍历二维网格中的每一个格子,对于每一个格子,如果格子 $grid[i][j]$ 未被访问过,我们就从该格子开始进行广度优先搜索,搜索过程中,我们需要记录每一个格子的父节点,以及上一个格子的坐标,如果下一个格子的值与当前格子的值相同,且不是上一个格子,并且已经被访问过,那么就说明存在环,返回 $\textit{true}$。遍历完所有格子后,如果没有找到环,返回 $\textit{false}$。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是二维网格的行数和列数。 @@ -87,21 +91,26 @@ tags: ```python 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) + vis = [[False] * n for _ in range(m)] + dirs = (-1, 0, 1, 0, -1) + for i, row in enumerate(grid): + for j, x in enumerate(row): + if vis[i][j]: + continue + vis[i][j] = True + q = [(i, j, -1, -1)] + while q: + x, y, px, py = q.pop() + for dx, dy in pairwise(dirs): + nx, ny = x + dx, y + dy + if 0 <= nx < m and 0 <= ny < n: + if grid[nx][ny] != grid[i][j] or (nx == px and ny == py): + continue + if vis[nx][ny]: + return True + vis[nx][ny] = True + q.append((nx, ny, x, y)) return False ``` @@ -109,39 +118,38 @@ class Solution: ```java 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}; + int m = grid.length, n = grid[0].length; + boolean[][] vis = new boolean[m][n]; + final int[] dirs = {-1, 0, 1, 0, -1}; 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; + if (!vis[i][j]) { + Deque q = new ArrayDeque<>(); + q.offer(new int[] {i, j, -1, -1}); + vis[i][j] = true; + while (!q.isEmpty()) { + int[] p = q.poll(); + int x = p[0], y = p[1], px = p[2], py = p[3]; + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.offer(new int[] {nx, ny, x, y}); + vis[nx][ny] = 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]; - } } ``` @@ -150,30 +158,41 @@ class Solution { ```cpp class Solution { public: - vector p; - bool containsCycle(vector>& 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 dirs = {0, 1, 0}; + vector> vis(m, vector(n)); + const vector dirs = {-1, 0, 1, 0, -1}; + 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); + if (!vis[i][j]) { + queue> q; + q.push({i, j, -1, -1}); + vis[i][j] = true; + + while (!q.empty()) { + auto p = q.front(); + q.pop(); + int x = p[0], y = p[1], px = p[2], py = p[3]; + + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.push({nx, ny, x, y}); + vis[nx][ny] = true; + } + } } } } } - return 0; - } - - int find(int x) { - if (p[x] != x) p[x] = find(p[x]); - return p[x]; + return false; } }; ``` @@ -183,27 +202,36 @@ public: ```go func containsCycle(grid [][]byte) bool { m, n := len(grid), len(grid[0]) - p := make([]int, m*n) - for i := range p { - p[i] = i + vis := make([][]bool, m) + for i := range vis { + vis[i] = make([]bool, n) } - 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} + dirs := []int{-1, 0, 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 + if !vis[i][j] { + q := [][]int{{i, j, -1, -1}} + vis[i][j] = true + + for len(q) > 0 { + p := q[0] + q = q[1:] + x, y, px, py := p[0], p[1], p[2], p[3] + + for k := 0; k < 4; k++ { + nx, ny := x+dirs[k], y+dirs[k+1] + if nx >= 0 && nx < m && ny >= 0 && ny < n { + if grid[nx][ny] != grid[x][y] || (nx == px && ny == py) { + continue + } + if vis[nx][ny] { + return true + } + q = append(q, []int{nx, ny, x, y}) + vis[nx][ny] = true + } } - p[find(x*n+y)] = find(i*n + j) } } } @@ -212,64 +240,83 @@ func containsCycle(grid [][]byte) bool { } ``` +#### TypeScript + +```ts +function containsCycle(grid: string[][]): boolean { + const [m, n] = [grid.length, grid[0].length]; + const vis: boolean[][] = Array.from({ length: m }, () => Array(n).fill(false)); + const dirs = [-1, 0, 1, 0, -1]; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (!vis[i][j]) { + const q: [number, number, number, number][] = [[i, j, -1, -1]]; + vis[i][j] = true; + for (const [x, y, px, py] of q) { + for (let k = 0; k < 4; k++) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] !== grid[x][y] || (nx === px && ny === py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.push([nx, ny, x, y]); + vis[nx][ny] = true; + } + } + } + } + } + } + return false; +} +``` + #### Rust ```rust impl Solution { - #[allow(dead_code)] pub fn contains_cycle(grid: Vec>) -> bool { - let n = grid.len(); - let m = grid[0].len(); - let mut d_set: Vec = vec![0; n * m]; - - // Initialize the disjoint set - for i in 0..n * m { - d_set[i] = i; - } - - // Traverse the grid - for i in 0..n { - for j in 0..m { - if i + 1 < n && grid[i + 1][j] == grid[i][j] { - // Check the below cell - let p_curr = Self::find(i * m + j, &mut d_set); - let p_below = Self::find((i + 1) * m + j, &mut d_set); - if p_curr == p_below { - return true; - } - // Otherwise, union the two cells - Self::union(p_curr, p_below, &mut d_set); - } - // Same to the right cell - if j + 1 < m && grid[i][j + 1] == grid[i][j] { - let p_curr = Self::find(i * m + j, &mut d_set); - let p_right = Self::find(i * m + (j + 1), &mut d_set); - if p_curr == p_right { - return true; + let m = grid.len(); + let n = grid[0].len(); + let mut vis = vec![vec![false; n]; m]; + let dirs = vec![-1, 0, 1, 0, -1]; + + for i in 0..m { + for j in 0..n { + if !vis[i][j] { + let mut q = vec![(i as isize, j as isize, -1, -1)]; + vis[i][j] = true; + + while !q.is_empty() { + let (x, y, px, py) = q.pop().unwrap(); + + for k in 0..4 { + let nx = x + dirs[k]; + let ny = y + dirs[k + 1]; + if nx >= 0 && nx < m as isize && ny >= 0 && ny < n as isize { + let nx = nx as usize; + let ny = ny as usize; + if grid[nx][ny] != grid[x as usize][y as usize] + || (nx == px as usize && ny == py as usize) + { + continue; + } + if vis[nx][ny] { + return true; + } + q.push((nx as isize, ny as isize, x, y)); + vis[nx][ny] = true; + } + } } - // Otherwise, union the two cells - Self::union(p_curr, p_right, &mut d_set); } } } - false } - - #[allow(dead_code)] - fn find(x: usize, d_set: &mut Vec) -> usize { - if d_set[x] != x { - d_set[x] = Self::find(d_set[x], d_set); - } - d_set[x] - } - - #[allow(dead_code)] - fn union(x: usize, y: usize, d_set: &mut Vec) { - let p_x = Self::find(x, d_set); - let p_y = Self::find(y, d_set); - d_set[p_x] = p_y; - } } ``` @@ -281,34 +328,274 @@ impl Solution { * @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]); + const [m, n] = [grid.length, grid[0].length]; + const vis = Array.from({ length: m }, () => Array(n).fill(false)); + const dirs = [-1, 0, 1, 0, -1]; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (!vis[i][j]) { + const q = [[i, j, -1, -1]]; + vis[i][j] = true; + for (const [x, y, px, py] of q) { + for (let k = 0; k < 4; k++) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] !== grid[x][y] || (nx === px && ny === py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.push([nx, ny, x, y]); + vis[nx][ny] = true; + } + } + } + } } - 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 false; +}; +``` + + + + + + + +### 方法二:DFS + +我们可以遍历二维网格中的每一个格子,对于每一个格子,如果格子 $grid[i][j]$ 未被访问过,我们就从该格子开始进行深度优先搜索,搜索过程中,我们需要记录每一个格子的父节点,以及上一个格子的坐标,如果下一个格子的值与当前格子的值相同,且不是上一个格子,并且已经被访问过,那么就说明存在环,返回 $\textit{true}$。遍历完所有格子后,如果没有找到环,返回 $\textit{false}$。 + +时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是二维网格的行数和列数。 + + + +#### Python3 + +```python +class Solution: + def containsCycle(self, grid: List[List[str]]) -> bool: + def dfs(x: int, y: int, px: int, py: int) -> bool: + vis[x][y] = True + for dx, dy in pairwise(dirs): + nx, ny = x + dx, y + dy + if 0 <= nx < m and 0 <= ny < n: + if grid[nx][ny] != grid[x][y] or (nx == px and ny == py): + continue + if vis[nx][ny] or dfs(nx, ny, x, y): + return True + return False + + m, n = len(grid), len(grid[0]) + vis = [[False] * n for _ in range(m)] + dirs = (-1, 0, 1, 0, -1) + for i in range(m): + for j in range(n): + if vis[i][j]: + continue + if dfs(i, j, -1, -1): + return True + return False +``` + +#### Java + +```java +class Solution { + private char[][] grid; + private boolean[][] vis; + private final int[] dirs = {-1, 0, 1, 0, -1}; + private int m; + private int n; + + public boolean containsCycle(char[][] grid) { + this.grid = grid; + m = grid.length; + n = grid[0].length; + vis = new boolean[m][n]; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + if (!vis[i][j] && dfs(i, j, -1, -1)) { + return true; + } + } + } + return false; + } + + private boolean dfs(int x, int y, int px, int py) { + vis[x][y] = true; + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny] || dfs(nx, ny, x, y)) { + return true; + } + } + } + return false; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + bool containsCycle(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + vector> vis(m, vector(n)); + const vector dirs = {-1, 0, 1, 0, -1}; + function dfs = [&](int x, int y, int px, int py) { + vis[x][y] = true; + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny] || dfs(nx, ny, x, y)) { return true; } - p[find(x * n + y)] = find(i * n + j); + } + } + return false; + }; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + if (!vis[i][j] && dfs(i, j, -1, -1)) { + return true; } } } + return false; } - return false; }; ``` +#### Go + +```go +func containsCycle(grid [][]byte) bool { + m, n := len(grid), len(grid[0]) + vis := make([][]bool, m) + for i := range vis { + vis[i] = make([]bool, n) + } + dirs := []int{-1, 0, 1, 0, -1} + var dfs func(x, y, px, py int) bool + dfs = func(x, y, px, py int) bool { + vis[x][y] = true + for k := 0; k < 4; k++ { + nx, ny := x+dirs[k], y+dirs[k+1] + if nx >= 0 && nx < m && ny >= 0 && ny < n { + if grid[nx][ny] != grid[x][y] || (nx == px && ny == py) { + continue + } + if vis[nx][ny] || dfs(nx, ny, x, y) { + return true + } + } + } + return false + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if !vis[i][j] && dfs(i, j, -1, -1) { + return true + } + } + } + return false +} +``` + +#### TypeScript + +```ts +function containsCycle(grid: string[][]): boolean { + const [m, n] = [grid.length, grid[0].length]; + const vis: boolean[][] = Array.from({ length: m }, () => Array(n).fill(false)); + const dfs = (x: number, y: number, px: number, py: number): boolean => { + vis[x][y] = true; + const dirs = [-1, 0, 1, 0, -1]; + for (let k = 0; k < 4; k++) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] !== grid[x][y] || (nx === px && ny === py)) { + continue; + } + if (vis[nx][ny] || dfs(nx, ny, x, y)) { + return true; + } + } + } + return false; + }; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (!vis[i][j] && dfs(i, j, -1, -1)) { + return true; + } + } + } + return false; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn contains_cycle(grid: Vec>) -> bool { + let m = grid.len(); + let n = grid[0].len(); + let mut vis = vec![vec![false; n]; m]; + let dirs = vec![-1, 0, 1, 0, -1]; + + fn dfs( + x: usize, + y: usize, + px: isize, + py: isize, + grid: &Vec>, + vis: &mut Vec>, + dirs: &Vec, + ) -> bool { + vis[x][y] = true; + for k in 0..4 { + let nx = (x as isize + dirs[k]) as usize; + let ny = (y as isize + dirs[k + 1]) as usize; + if nx < grid.len() && ny < grid[0].len() { + if grid[nx][ny] != grid[x][y] || (nx as isize == px && ny as isize == py) { + continue; + } + if vis[nx][ny] || dfs(nx, ny, x as isize, y as isize, grid, vis, dirs) { + return true; + } + } + } + false + } + + for i in 0..m { + for j in 0..n { + if !vis[i][j] && dfs(i, j, -1, -1, &grid, &mut vis, &dirs) { + return true; + } + } + } + false + } +} +``` + diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/README_EN.md b/solution/1500-1599/1559.Detect Cycles in 2D Grid/README_EN.md index a2196440a7991..f8ab55a046199 100644 --- a/solution/1500-1599/1559.Detect Cycles in 2D Grid/README_EN.md +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/README_EN.md @@ -78,7 +78,11 @@ tags: -### Solution 1 +### Solution 1: BFS + +We can traverse each cell in the 2D grid. For each cell, if the cell $grid[i][j]$ has not been visited, we start a breadth-first search (BFS) from that cell. During the search, we need to record the parent node of each cell and the coordinates of the previous cell. If the value of the next cell is the same as the current cell, and it is not the previous cell, and it has already been visited, then it indicates the presence of a cycle, and we return $\textit{true}$. After traversing all cells, if no cycle is found, we return $\textit{false}$. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the number of rows and columns of the 2D grid, respectively. @@ -87,21 +91,26 @@ tags: ```python 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) + vis = [[False] * n for _ in range(m)] + dirs = (-1, 0, 1, 0, -1) + for i, row in enumerate(grid): + for j, x in enumerate(row): + if vis[i][j]: + continue + vis[i][j] = True + q = [(i, j, -1, -1)] + while q: + x, y, px, py = q.pop() + for dx, dy in pairwise(dirs): + nx, ny = x + dx, y + dy + if 0 <= nx < m and 0 <= ny < n: + if grid[nx][ny] != grid[i][j] or (nx == px and ny == py): + continue + if vis[nx][ny]: + return True + vis[nx][ny] = True + q.append((nx, ny, x, y)) return False ``` @@ -109,39 +118,38 @@ class Solution: ```java 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}; + int m = grid.length, n = grid[0].length; + boolean[][] vis = new boolean[m][n]; + final int[] dirs = {-1, 0, 1, 0, -1}; 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; + if (!vis[i][j]) { + Deque q = new ArrayDeque<>(); + q.offer(new int[] {i, j, -1, -1}); + vis[i][j] = true; + while (!q.isEmpty()) { + int[] p = q.poll(); + int x = p[0], y = p[1], px = p[2], py = p[3]; + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.offer(new int[] {nx, ny, x, y}); + vis[nx][ny] = 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]; - } } ``` @@ -150,30 +158,41 @@ class Solution { ```cpp class Solution { public: - vector p; - bool containsCycle(vector>& 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 dirs = {0, 1, 0}; + vector> vis(m, vector(n)); + const vector dirs = {-1, 0, 1, 0, -1}; + 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); + if (!vis[i][j]) { + queue> q; + q.push({i, j, -1, -1}); + vis[i][j] = true; + + while (!q.empty()) { + auto p = q.front(); + q.pop(); + int x = p[0], y = p[1], px = p[2], py = p[3]; + + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.push({nx, ny, x, y}); + vis[nx][ny] = true; + } + } } } } } - return 0; - } - - int find(int x) { - if (p[x] != x) p[x] = find(p[x]); - return p[x]; + return false; } }; ``` @@ -183,27 +202,36 @@ public: ```go func containsCycle(grid [][]byte) bool { m, n := len(grid), len(grid[0]) - p := make([]int, m*n) - for i := range p { - p[i] = i + vis := make([][]bool, m) + for i := range vis { + vis[i] = make([]bool, n) } - 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} + dirs := []int{-1, 0, 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 + if !vis[i][j] { + q := [][]int{{i, j, -1, -1}} + vis[i][j] = true + + for len(q) > 0 { + p := q[0] + q = q[1:] + x, y, px, py := p[0], p[1], p[2], p[3] + + for k := 0; k < 4; k++ { + nx, ny := x+dirs[k], y+dirs[k+1] + if nx >= 0 && nx < m && ny >= 0 && ny < n { + if grid[nx][ny] != grid[x][y] || (nx == px && ny == py) { + continue + } + if vis[nx][ny] { + return true + } + q = append(q, []int{nx, ny, x, y}) + vis[nx][ny] = true + } } - p[find(x*n+y)] = find(i*n + j) } } } @@ -212,64 +240,83 @@ func containsCycle(grid [][]byte) bool { } ``` +#### TypeScript + +```ts +function containsCycle(grid: string[][]): boolean { + const [m, n] = [grid.length, grid[0].length]; + const vis: boolean[][] = Array.from({ length: m }, () => Array(n).fill(false)); + const dirs = [-1, 0, 1, 0, -1]; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (!vis[i][j]) { + const q: [number, number, number, number][] = [[i, j, -1, -1]]; + vis[i][j] = true; + for (const [x, y, px, py] of q) { + for (let k = 0; k < 4; k++) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] !== grid[x][y] || (nx === px && ny === py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.push([nx, ny, x, y]); + vis[nx][ny] = true; + } + } + } + } + } + } + return false; +} +``` + #### Rust ```rust impl Solution { - #[allow(dead_code)] pub fn contains_cycle(grid: Vec>) -> bool { - let n = grid.len(); - let m = grid[0].len(); - let mut d_set: Vec = vec![0; n * m]; - - // Initialize the disjoint set - for i in 0..n * m { - d_set[i] = i; - } - - // Traverse the grid - for i in 0..n { - for j in 0..m { - if i + 1 < n && grid[i + 1][j] == grid[i][j] { - // Check the below cell - let p_curr = Self::find(i * m + j, &mut d_set); - let p_below = Self::find((i + 1) * m + j, &mut d_set); - if p_curr == p_below { - return true; - } - // Otherwise, union the two cells - Self::union(p_curr, p_below, &mut d_set); - } - // Same to the right cell - if j + 1 < m && grid[i][j + 1] == grid[i][j] { - let p_curr = Self::find(i * m + j, &mut d_set); - let p_right = Self::find(i * m + (j + 1), &mut d_set); - if p_curr == p_right { - return true; + let m = grid.len(); + let n = grid[0].len(); + let mut vis = vec![vec![false; n]; m]; + let dirs = vec![-1, 0, 1, 0, -1]; + + for i in 0..m { + for j in 0..n { + if !vis[i][j] { + let mut q = vec![(i as isize, j as isize, -1, -1)]; + vis[i][j] = true; + + while !q.is_empty() { + let (x, y, px, py) = q.pop().unwrap(); + + for k in 0..4 { + let nx = x + dirs[k]; + let ny = y + dirs[k + 1]; + if nx >= 0 && nx < m as isize && ny >= 0 && ny < n as isize { + let nx = nx as usize; + let ny = ny as usize; + if grid[nx][ny] != grid[x as usize][y as usize] + || (nx == px as usize && ny == py as usize) + { + continue; + } + if vis[nx][ny] { + return true; + } + q.push((nx as isize, ny as isize, x, y)); + vis[nx][ny] = true; + } + } } - // Otherwise, union the two cells - Self::union(p_curr, p_right, &mut d_set); } } } - false } - - #[allow(dead_code)] - fn find(x: usize, d_set: &mut Vec) -> usize { - if d_set[x] != x { - d_set[x] = Self::find(d_set[x], d_set); - } - d_set[x] - } - - #[allow(dead_code)] - fn union(x: usize, y: usize, d_set: &mut Vec) { - let p_x = Self::find(x, d_set); - let p_y = Self::find(y, d_set); - d_set[p_x] = p_y; - } } ``` @@ -281,34 +328,274 @@ impl Solution { * @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]); + const [m, n] = [grid.length, grid[0].length]; + const vis = Array.from({ length: m }, () => Array(n).fill(false)); + const dirs = [-1, 0, 1, 0, -1]; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (!vis[i][j]) { + const q = [[i, j, -1, -1]]; + vis[i][j] = true; + for (const [x, y, px, py] of q) { + for (let k = 0; k < 4; k++) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] !== grid[x][y] || (nx === px && ny === py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.push([nx, ny, x, y]); + vis[nx][ny] = true; + } + } + } + } } - 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 false; +}; +``` + + + + + + + +### Solution 2: DFS + +We can traverse each cell in the 2D grid. For each cell, if the cell $grid[i][j]$ has not been visited, we start a depth-first search (DFS) from that cell. During the search, we need to record the parent node of each cell and the coordinates of the previous cell. If the value of the next cell is the same as the current cell, and it is not the previous cell, and it has already been visited, then it indicates the presence of a cycle, and we return $\textit{true}$. After traversing all cells, if no cycle is found, we return $\textit{false}$. + +The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the number of rows and columns of the 2D grid, respectively. + + + +#### Python3 + +```python +class Solution: + def containsCycle(self, grid: List[List[str]]) -> bool: + def dfs(x: int, y: int, px: int, py: int) -> bool: + vis[x][y] = True + for dx, dy in pairwise(dirs): + nx, ny = x + dx, y + dy + if 0 <= nx < m and 0 <= ny < n: + if grid[nx][ny] != grid[x][y] or (nx == px and ny == py): + continue + if vis[nx][ny] or dfs(nx, ny, x, y): + return True + return False + + m, n = len(grid), len(grid[0]) + vis = [[False] * n for _ in range(m)] + dirs = (-1, 0, 1, 0, -1) + for i in range(m): + for j in range(n): + if vis[i][j]: + continue + if dfs(i, j, -1, -1): + return True + return False +``` + +#### Java + +```java +class Solution { + private char[][] grid; + private boolean[][] vis; + private final int[] dirs = {-1, 0, 1, 0, -1}; + private int m; + private int n; + + public boolean containsCycle(char[][] grid) { + this.grid = grid; + m = grid.length; + n = grid[0].length; + vis = new boolean[m][n]; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + if (!vis[i][j] && dfs(i, j, -1, -1)) { + return true; + } + } + } + return false; + } + + private boolean dfs(int x, int y, int px, int py) { + vis[x][y] = true; + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny] || dfs(nx, ny, x, y)) { + return true; + } + } + } + return false; + } +} +``` + +#### C++ + +```cpp +class Solution { +public: + bool containsCycle(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + vector> vis(m, vector(n)); + const vector dirs = {-1, 0, 1, 0, -1}; + function dfs = [&](int x, int y, int px, int py) { + vis[x][y] = true; + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny] || dfs(nx, ny, x, y)) { return true; } - p[find(x * n + y)] = find(i * n + j); + } + } + return false; + }; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + if (!vis[i][j] && dfs(i, j, -1, -1)) { + return true; } } } + return false; } - return false; }; ``` +#### Go + +```go +func containsCycle(grid [][]byte) bool { + m, n := len(grid), len(grid[0]) + vis := make([][]bool, m) + for i := range vis { + vis[i] = make([]bool, n) + } + dirs := []int{-1, 0, 1, 0, -1} + var dfs func(x, y, px, py int) bool + dfs = func(x, y, px, py int) bool { + vis[x][y] = true + for k := 0; k < 4; k++ { + nx, ny := x+dirs[k], y+dirs[k+1] + if nx >= 0 && nx < m && ny >= 0 && ny < n { + if grid[nx][ny] != grid[x][y] || (nx == px && ny == py) { + continue + } + if vis[nx][ny] || dfs(nx, ny, x, y) { + return true + } + } + } + return false + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if !vis[i][j] && dfs(i, j, -1, -1) { + return true + } + } + } + return false +} +``` + +#### TypeScript + +```ts +function containsCycle(grid: string[][]): boolean { + const [m, n] = [grid.length, grid[0].length]; + const vis: boolean[][] = Array.from({ length: m }, () => Array(n).fill(false)); + const dfs = (x: number, y: number, px: number, py: number): boolean => { + vis[x][y] = true; + const dirs = [-1, 0, 1, 0, -1]; + for (let k = 0; k < 4; k++) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] !== grid[x][y] || (nx === px && ny === py)) { + continue; + } + if (vis[nx][ny] || dfs(nx, ny, x, y)) { + return true; + } + } + } + return false; + }; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (!vis[i][j] && dfs(i, j, -1, -1)) { + return true; + } + } + } + return false; +} +``` + +#### Rust + +```rust +impl Solution { + pub fn contains_cycle(grid: Vec>) -> bool { + let m = grid.len(); + let n = grid[0].len(); + let mut vis = vec![vec![false; n]; m]; + let dirs = vec![-1, 0, 1, 0, -1]; + + fn dfs( + x: usize, + y: usize, + px: isize, + py: isize, + grid: &Vec>, + vis: &mut Vec>, + dirs: &Vec, + ) -> bool { + vis[x][y] = true; + for k in 0..4 { + let nx = (x as isize + dirs[k]) as usize; + let ny = (y as isize + dirs[k + 1]) as usize; + if nx < grid.len() && ny < grid[0].len() { + if grid[nx][ny] != grid[x][y] || (nx as isize == px && ny as isize == py) { + continue; + } + if vis[nx][ny] || dfs(nx, ny, x as isize, y as isize, grid, vis, dirs) { + return true; + } + } + } + false + } + + for i in 0..m { + for j in 0..n { + if !vis[i][j] && dfs(i, j, -1, -1, &grid, &mut vis, &dirs) { + return true; + } + } + } + false + } +} +``` + diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.cpp b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.cpp index b56f469eb205f..c5271446eaaad 100644 --- a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.cpp +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.cpp @@ -1,28 +1,39 @@ -class Solution { -public: - vector p; - - bool containsCycle(vector>& 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 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]; - } -}; \ No newline at end of file +class Solution { +public: + bool containsCycle(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + vector> vis(m, vector(n)); + const vector dirs = {-1, 0, 1, 0, -1}; + + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + if (!vis[i][j]) { + queue> q; + q.push({i, j, -1, -1}); + vis[i][j] = true; + + while (!q.empty()) { + auto p = q.front(); + q.pop(); + int x = p[0], y = p[1], px = p[2], py = p[3]; + + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.push({nx, ny, x, y}); + vis[nx][ny] = true; + } + } + } + } + } + } + return false; + } +}; diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.go b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.go index 391ec40eebba9..759de958a5100 100644 --- a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.go +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.go @@ -1,29 +1,38 @@ -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 -} \ No newline at end of file +func containsCycle(grid [][]byte) bool { + m, n := len(grid), len(grid[0]) + vis := make([][]bool, m) + for i := range vis { + vis[i] = make([]bool, n) + } + dirs := []int{-1, 0, 1, 0, -1} + + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if !vis[i][j] { + q := [][]int{{i, j, -1, -1}} + vis[i][j] = true + + for len(q) > 0 { + p := q[0] + q = q[1:] + x, y, px, py := p[0], p[1], p[2], p[3] + + for k := 0; k < 4; k++ { + nx, ny := x+dirs[k], y+dirs[k+1] + if nx >= 0 && nx < m && ny >= 0 && ny < n { + if grid[nx][ny] != grid[x][y] || (nx == px && ny == py) { + continue + } + if vis[nx][ny] { + return true + } + q = append(q, []int{nx, ny, x, y}) + vis[nx][ny] = true + } + } + } + } + } + } + return false +} diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.java b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.java index 414fe0da9c36b..2d0eb42ddb1e0 100644 --- a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.java +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.java @@ -1,35 +1,34 @@ -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]; - } -} \ No newline at end of file +class Solution { + public boolean containsCycle(char[][] grid) { + int m = grid.length, n = grid[0].length; + boolean[][] vis = new boolean[m][n]; + final int[] dirs = {-1, 0, 1, 0, -1}; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + if (!vis[i][j]) { + Deque q = new ArrayDeque<>(); + q.offer(new int[] {i, j, -1, -1}); + vis[i][j] = true; + while (!q.isEmpty()) { + int[] p = q.poll(); + int x = p[0], y = p[1], px = p[2], py = p[3]; + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.offer(new int[] {nx, ny, x, y}); + vis[nx][ny] = true; + } + } + } + } + } + } + return false; + } +} diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.js b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.js index f052bf700883c..2ee33bbf04283 100644 --- a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.js +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.js @@ -3,26 +3,28 @@ * @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; + const [m, n] = [grid.length, grid[0].length]; + const vis = Array.from({ length: m }, () => Array(n).fill(false)); + const dirs = [-1, 0, 1, 0, -1]; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (!vis[i][j]) { + const q = [[i, j, -1, -1]]; + vis[i][j] = true; + for (const [x, y, px, py] of q) { + for (let k = 0; k < 4; k++) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] !== grid[x][y] || (nx === px && ny === py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.push([nx, ny, x, y]); + vis[nx][ny] = true; + } } - p[find(x * n + y)] = find(i * n + j); } } } diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.py b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.py index 7073d095e41ef..6ff60f9c4e1b0 100644 --- a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.py +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.py @@ -1,18 +1,23 @@ -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: + def containsCycle(self, grid: List[List[str]]) -> bool: + m, n = len(grid), len(grid[0]) + vis = [[False] * n for _ in range(m)] + dirs = (-1, 0, 1, 0, -1) + for i, row in enumerate(grid): + for j, x in enumerate(row): + if vis[i][j]: + continue + vis[i][j] = True + q = [(i, j, -1, -1)] + while q: + x, y, px, py = q.pop() + for dx, dy in pairwise(dirs): + nx, ny = x + dx, y + dy + if 0 <= nx < m and 0 <= ny < n: + if grid[nx][ny] != grid[i][j] or (nx == px and ny == py): + continue + if vis[nx][ny]: + return True + vis[nx][ny] = True + q.append((nx, ny, x, y)) + return False diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.rs b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.rs index 34d14923c4db3..dfdaeec6c5f60 100644 --- a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.rs +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.rs @@ -1,56 +1,41 @@ -impl Solution { - #[allow(dead_code)] - pub fn contains_cycle(grid: Vec>) -> bool { - let n = grid.len(); - let m = grid[0].len(); - let mut d_set: Vec = vec![0; n * m]; - - // Initialize the disjoint set - for i in 0..n * m { - d_set[i] = i; - } - - // Traverse the grid - for i in 0..n { - for j in 0..m { - if i + 1 < n && grid[i + 1][j] == grid[i][j] { - // Check the below cell - let p_curr = Self::find(i * m + j, &mut d_set); - let p_below = Self::find((i + 1) * m + j, &mut d_set); - if p_curr == p_below { - return true; - } - // Otherwise, union the two cells - Self::union(p_curr, p_below, &mut d_set); - } - // Same to the right cell - if j + 1 < m && grid[i][j + 1] == grid[i][j] { - let p_curr = Self::find(i * m + j, &mut d_set); - let p_right = Self::find(i * m + (j + 1), &mut d_set); - if p_curr == p_right { - return true; - } - // Otherwise, union the two cells - Self::union(p_curr, p_right, &mut d_set); - } - } - } - - false - } - - #[allow(dead_code)] - fn find(x: usize, d_set: &mut Vec) -> usize { - if d_set[x] != x { - d_set[x] = Self::find(d_set[x], d_set); - } - d_set[x] - } - - #[allow(dead_code)] - fn union(x: usize, y: usize, d_set: &mut Vec) { - let p_x = Self::find(x, d_set); - let p_y = Self::find(y, d_set); - d_set[p_x] = p_y; - } -} +impl Solution { + pub fn contains_cycle(grid: Vec>) -> bool { + let m = grid.len(); + let n = grid[0].len(); + let mut vis = vec![vec![false; n]; m]; + let dirs = vec![-1, 0, 1, 0, -1]; + + for i in 0..m { + for j in 0..n { + if !vis[i][j] { + let mut q = vec![(i as isize, j as isize, -1, -1)]; + vis[i][j] = true; + + while !q.is_empty() { + let (x, y, px, py) = q.pop().unwrap(); + + for k in 0..4 { + let nx = x + dirs[k]; + let ny = y + dirs[k + 1]; + if nx >= 0 && nx < m as isize && ny >= 0 && ny < n as isize { + let nx = nx as usize; + let ny = ny as usize; + if grid[nx][ny] != grid[x as usize][y as usize] + || (nx == px as usize && ny == py as usize) + { + continue; + } + if vis[nx][ny] { + return true; + } + q.push((nx as isize, ny as isize, x, y)); + vis[nx][ny] = true; + } + } + } + } + } + } + false + } +} diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.ts b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.ts new file mode 100644 index 0000000000000..61d9d6b2aa466 --- /dev/null +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution.ts @@ -0,0 +1,29 @@ +function containsCycle(grid: string[][]): boolean { + const [m, n] = [grid.length, grid[0].length]; + const vis: boolean[][] = Array.from({ length: m }, () => Array(n).fill(false)); + const dirs = [-1, 0, 1, 0, -1]; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (!vis[i][j]) { + const q: [number, number, number, number][] = [[i, j, -1, -1]]; + vis[i][j] = true; + for (const [x, y, px, py] of q) { + for (let k = 0; k < 4; k++) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] !== grid[x][y] || (nx === px && ny === py)) { + continue; + } + if (vis[nx][ny]) { + return true; + } + q.push([nx, ny, x, y]); + vis[nx][ny] = true; + } + } + } + } + } + } + return false; +} diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.cpp b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.cpp new file mode 100644 index 0000000000000..92575b73f06fc --- /dev/null +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.cpp @@ -0,0 +1,31 @@ +class Solution { +public: + bool containsCycle(vector>& grid) { + int m = grid.size(), n = grid[0].size(); + vector> vis(m, vector(n)); + const vector dirs = {-1, 0, 1, 0, -1}; + function dfs = [&](int x, int y, int px, int py) { + vis[x][y] = true; + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny] || dfs(nx, ny, x, y)) { + return true; + } + } + } + return false; + }; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + if (!vis[i][j] && dfs(i, j, -1, -1)) { + return true; + } + } + } + return false; + } +}; diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.go b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.go new file mode 100644 index 0000000000000..bc0715ab9a691 --- /dev/null +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.go @@ -0,0 +1,32 @@ +func containsCycle(grid [][]byte) bool { + m, n := len(grid), len(grid[0]) + vis := make([][]bool, m) + for i := range vis { + vis[i] = make([]bool, n) + } + dirs := []int{-1, 0, 1, 0, -1} + var dfs func(x, y, px, py int) bool + dfs = func(x, y, px, py int) bool { + vis[x][y] = true + for k := 0; k < 4; k++ { + nx, ny := x+dirs[k], y+dirs[k+1] + if nx >= 0 && nx < m && ny >= 0 && ny < n { + if grid[nx][ny] != grid[x][y] || (nx == px && ny == py) { + continue + } + if vis[nx][ny] || dfs(nx, ny, x, y) { + return true + } + } + } + return false + } + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if !vis[i][j] && dfs(i, j, -1, -1) { + return true + } + } + } + return false +} diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.java b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.java new file mode 100644 index 0000000000000..e32b160c5bf99 --- /dev/null +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.java @@ -0,0 +1,38 @@ +class Solution { + private char[][] grid; + private boolean[][] vis; + private final int[] dirs = {-1, 0, 1, 0, -1}; + private int m; + private int n; + + public boolean containsCycle(char[][] grid) { + this.grid = grid; + m = grid.length; + n = grid[0].length; + vis = new boolean[m][n]; + for (int i = 0; i < m; ++i) { + for (int j = 0; j < n; ++j) { + if (!vis[i][j] && dfs(i, j, -1, -1)) { + return true; + } + } + } + return false; + } + + private boolean dfs(int x, int y, int px, int py) { + vis[x][y] = true; + for (int k = 0; k < 4; ++k) { + int nx = x + dirs[k], ny = y + dirs[k + 1]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] != grid[x][y] || (nx == px && ny == py)) { + continue; + } + if (vis[nx][ny] || dfs(nx, ny, x, y)) { + return true; + } + } + } + return false; + } +} diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.py b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.py new file mode 100644 index 0000000000000..7f43ea23f8282 --- /dev/null +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.py @@ -0,0 +1,23 @@ +class Solution: + def containsCycle(self, grid: List[List[str]]) -> bool: + def dfs(x: int, y: int, px: int, py: int) -> bool: + vis[x][y] = True + for dx, dy in pairwise(dirs): + nx, ny = x + dx, y + dy + if 0 <= nx < m and 0 <= ny < n: + if grid[nx][ny] != grid[x][y] or (nx == px and ny == py): + continue + if vis[nx][ny] or dfs(nx, ny, x, y): + return True + return False + + m, n = len(grid), len(grid[0]) + vis = [[False] * n for _ in range(m)] + dirs = (-1, 0, 1, 0, -1) + for i in range(m): + for j in range(n): + if vis[i][j]: + continue + if dfs(i, j, -1, -1): + return True + return False diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.rs b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.rs new file mode 100644 index 0000000000000..8d929ae5c76f4 --- /dev/null +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.rs @@ -0,0 +1,42 @@ +impl Solution { + pub fn contains_cycle(grid: Vec>) -> bool { + let m = grid.len(); + let n = grid[0].len(); + let mut vis = vec![vec![false; n]; m]; + let dirs = vec![-1, 0, 1, 0, -1]; + + fn dfs( + x: usize, + y: usize, + px: isize, + py: isize, + grid: &Vec>, + vis: &mut Vec>, + dirs: &Vec, + ) -> bool { + vis[x][y] = true; + for k in 0..4 { + let nx = (x as isize + dirs[k]) as usize; + let ny = (y as isize + dirs[k + 1]) as usize; + if nx < grid.len() && ny < grid[0].len() { + if grid[nx][ny] != grid[x][y] || (nx as isize == px && ny as isize == py) { + continue; + } + if vis[nx][ny] || dfs(nx, ny, x as isize, y as isize, grid, vis, dirs) { + return true; + } + } + } + false + } + + for i in 0..m { + for j in 0..n { + if !vis[i][j] && dfs(i, j, -1, -1, &grid, &mut vis, &dirs) { + return true; + } + } + } + false + } +} diff --git a/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.ts b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.ts new file mode 100644 index 0000000000000..91a635f5c13fd --- /dev/null +++ b/solution/1500-1599/1559.Detect Cycles in 2D Grid/Solution2.ts @@ -0,0 +1,28 @@ +function containsCycle(grid: string[][]): boolean { + const [m, n] = [grid.length, grid[0].length]; + const vis: boolean[][] = Array.from({ length: m }, () => Array(n).fill(false)); + const dfs = (x: number, y: number, px: number, py: number): boolean => { + vis[x][y] = true; + const dirs = [-1, 0, 1, 0, -1]; + for (let k = 0; k < 4; k++) { + const [nx, ny] = [x + dirs[k], y + dirs[k + 1]]; + if (nx >= 0 && nx < m && ny >= 0 && ny < n) { + if (grid[nx][ny] !== grid[x][y] || (nx === px && ny === py)) { + continue; + } + if (vis[nx][ny] || dfs(nx, ny, x, y)) { + return true; + } + } + } + return false; + }; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (!vis[i][j] && dfs(i, j, -1, -1)) { + return true; + } + } + } + return false; +}