Posted onEdited onInLeetcode
,
HardViews: Valine: Symbols count in article: 7.6kReading time ≈7 mins.
Description
Difficulty: Hard
Given a 2D array of characters grid of size m x n, you need to find if there exists any cycle consisting of the same value in grid.
A cycle is a path of length 4 or more in the grid that starts and ends at the same cell. From a given cell, you can move to one of the cells adjacent to it in one of the four directions (up, down, left, or right), if it has the same value of the current cell.
Also, you cannot move to the cell that you visited in your last move. For example, the cycle (1, 1) -> (1, 2) -> (1, 1) is invalid because from (1, 2) we visited (1, 1) which was the last visited cell.
Return true if any cycle of the same value exists in grid, otherwise, return false.
Example 1:
1 2 3 4 5 6 7 8
Input: grid = [ ["a","a","a","a"], ["a","b","b","a"], ["a","b","b","a"], ["a","a","a","a"] ] Output: true Explanation: There are two valid cycles。
Example 2:
1 2 3 4 5 6 7 8
Input: grid = [ ["c","c","c","a"], ["c","d","c","c"], ["c","c","e","c"], ["f","c","c","c"] ] Output: true Explanation: There is only one valid cycle highlighted in the image below:
classSolution{ publicbooleancontainsCycle(char[][] grid){ int x = grid.length; int y = grid[0].length; for(int i=0; i<x; i++){ for(int j=0; j<y;j++){ char c = grid[i][j]; grid[i][j] = '!'; // mark the first char if(dfs(grid, c, i, j, 1)) returntrue; grid[i][j] = c; // set back } } returnfalse; } publicbooleandfs(char[][] grid, char c, int x, int y, int z){ if(x<0 || x>grid.length-1 || y<0 || y>grid[0].length-1){ returnfalse; // outside of the border }
if(grid[x][y] == '!' && z < 4 && z != 1){ returnfalse; // prevent from the second to the first one } if(grid[x][y] == '!' && z >= 4){ returntrue; // find the cycle } if(grid[x][y] != c){ if(z != 1) returnfalse; // notice that the first one is also != c }
char tmp = grid[x][y]; if(z != 1) grid[x][y] = '.'; // mark the other char boolean b = dfs(grid, c, x+1, y, z+1) || dfs(grid, c, x-1, y, z+1) || dfs(grid, c, x, y-1, z+1) || dfs(grid, c, x, y+1, z+1); grid[x][y] = tmp; // set back return b; } }
classSolution{ publicbooleancontainsCycle(char[][] grid){ int x = grid.length; int y = grid[0].length; if(x == 0 || y == 0) returnfalse;
int[][] finished = newint[x][y]; for(int i=0; i<x; i++){ for(int j=0; j<y;j++){ finished[i][j] = 1; // the first // to the second one if(dfs(grid, finished, grid[i][j], i, j, 2)) returntrue; finished = newint[x][y]; } } returnfalse; } publicbooleandfs(char[][] grid, int[][] finished, char c, int x, int y, int z){ if( x!=0 && grid[x-1][y] == c){ // if(grid[x-1][y] != c) return false; // wrong, because we need to proof the other case below, never return false if(finished[x-1][y] != 0){ if(z - finished[x-1][y] >= 4) returntrue; // if(z - finished[x-1][y] == 2) return false; the same here } elseif(finished[x-1][y] == 0){ finished[x-1][y] = z; if(dfs(grid, finished, c, x-1, y, z+1)) returntrue; finished[x-1][y] = 0; } }
classSolution{ int[][] direction = {{1,0},{-1,0},{0,1},{0,-1}}; // four possible position change publicbooleancontainsCycle(char[][] grid){ int x = grid.length; int y = grid[0].length; if(x == 0 || y == 0) returnfalse;
int[][] visited = newint[x][y]; for(int i=0; i<x; i++){ for(int j=0; j<y;j++){ if(visited[i][j] == 1) continue; if(dfs(grid, visited, grid[i][j], i, j, -1, -1)) returntrue; } } returnfalse; } publicbooleandfs(char[][] grid, int[][] visited, char c, int x, int y, int lx, int ly){ if(visited[x][y] == 1) returntrue; // we find the cycle visited[x][y] = 1; for(int[] d: direction){ int nx = x + d[0]; // first number int ny = y + d[1]; // second number if(nx == lx && ny == ly) continue; // next = last if(nx < 0 || nx>grid.length-1 || ny<0 || ny>grid[0].length-1 || grid[nx][ny] != c) continue; if(dfs(grid, visited, c, nx, ny, x, y)) returntrue; } returnfalse; } }
classSolution{ publicbooleancontainsCycle(char[][] grid){ int h = grid.length; int w = grid[0].length; DSU dsu = new DSU(w * h); for (int i = 0; i < h; ++i) { for (int j = 0; j < w; ++j) { char cur = grid[i][j]; // 向右搜索 if (j + 1 < w && cur == grid[i][j + 1]) { if (dsu.union(i * w + j, i * w + j + 1)) { returntrue; } } // 向下搜索 if (i + 1 < h && cur == grid[i + 1][j]) { if (dsu.union(i * w + j, (i + 1) * w + j)) { returntrue; } } } } returnfalse; }
classDSU{ int[] parent;
publicDSU(int N){ parent = newint[N]; for (int i = 0; i < N; ++i) { parent[i] = i; } }