Maze Problem
130. 被围绕的区域

方法一:DFS
从边界出发,把边界以及与边界连通的O
标记为B`遍历整个board,把
B还原为O,把O(此时的O是被X包围的)改变为X没有这句死循环,m == 1,( i += 0)
if (m <= 2 || n <= 2) return;
1 | |

方法二:BFS
1 | |
方法三:并查集
1 | |
200. 岛屿数量

方法一:DFS
1 | |

方法二:BFS
1 | |

329. 矩阵中的最长递增路径

方法一:DFS + 记忆化搜索
如果之前计算过dp[i][j],直接返回dp[i][j]
计算从matrix[i][j]为起点的最长路径,并用max记录最大值
1
2if (isValid(row, col) && matrix[row][col] > matrix[i][j]) {
max = Math.max(max, dfs(row, col, matrix));返回上一个节点的时候需要加上1,因为当前节点也需要加上,并用dp[i][j]记录
1
return dp[i][j] = max + 1;
1 | |

二刷
1 | |
417. 太平洋大西洋水流问题

三刷DFS
1 | |
二刷DFS
把四条边先标记好,然后dfs
1 | |

463. 岛屿的周长

方法一:DFS
- 初始每个陆地的边长都为4,如果周围有一个相连的陆地,那么周长-1,如上图grid[1][1],上下左右都有陆地,所以它拥有的边长为4 - 4 = 0
- 只要陆地i, j的邻居row, col不是水域,那么先将周长减一
- 如果grid[row][col] == 2,说明之前访问过,不需要继续dfs,但是需要讲周长减一
- 如果grid[row][col] == 1,周长需要减一并且需要dfs访问
1 | |
代码
1 | |
方法二:BFS
1 | |
695. 岛屿的最大面积

方法一:DFS
1 | |

方法二:并查集
注意
只有当grid[i][j] == 1时才判断
如果row,col不超过边界,且grid[row][col]是陆地(1或者2),且没有被访问过(如果访问过,
那么grid[i][j]与grid[row][col]的parent一致),则将grid[i][j]赋值2(1表示没有被访问的陆地,2表示被访问过的陆地)
如果row,col不超过边界,且grid[row][col]是陆地(1或者2),但是被访问过(此时也会绑定grid[i][j]与grid[row][col]的parent),不执行
1
2
3
4
5
6
7
8if (grid[i][j] == 1) {
for (int[] dir : dirs) {
int row = i + dir[0], col = j + dir[1];
// 1.不超过边界 2.是陆地 3.没有被访问过
if (isValid(row, col) && grid[row][col] != 0 && union(i * n + j, row * n + col))
grid[i][j] = 2;
}
}遍历所有陆地,将每块陆地的祖先存入map,值为子孙的数量,那么含有最大子孙的数量就是岛屿最大数量
map进行put操作时,key为
findParent(i * n + j),因为在之前进行union的过程(parent[parentOfI] = parentOfJ),直接将i的祖先的祖先赋值为j的祖先,但是此时i的祖先还没有同步,所以这里是进行一个祖先同步的操作1
2
3
4
5
6
7Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
if (grid[i][j] != 0) {
map.put(findParent(i * n + j), map.getOrDefault(parent[i * n + j], 0) + 1);
res = Math.max(res, map.get(parent[i * n + j]));
}
代码
1 | |
二刷并查集
1 | |
733. 图像渲染

方法一:BFS
二刷
1 | |
一刷
小心死循环,curColor很关键
1 | |
方法二:DFS
1 | |

1020. 飞地的数量

方法一:DFS
同太平洋大西洋水流问题,从边缘进入dfs
1 | |

方法二:BFS
1 | |

方法三:并查集
遍历矩阵,只检查左边和上面,可以保证每一条边的两个节点只会被合并一次
1 | |
方法一:BFS
每次从队列中取出一个节点时,记录当前队列大小size,初始化neigbors = 0
在上下左右四个方向遍历,如果相邻节点没有越界且与当前字符相同,++neighbors,如果没访问过,加入队列,visited赋值true
遍历完四个方向后,如果neigbors - 1== queue.size() - size,(-1是减去上一次访问过,并将当前节点入队的节点),说明新入队的邻居之前都没有访问过
如果neigbors - 1 > queue.size() - size,说明遍历到了已经访问过的jie'dian,那么可以形成环
举例

从下标(0, 0)开始BFS遍历,有两条路径,一条向右出发(记为路径A),一条向下出发(记为路径B),这里默认先遍历右边再遍历下面
当遍历了5步后,如下图

(路径A)此时下标为(2, 3)的节点往下遍历,将右下角编号为(3, 3)的节点赋值true,如下图

(路径B)现在下标为(3, 2)的节点往右遍历,邻居neighbors = 2,但是queue.size() - size = 0(队列没有新入队节点),说明路径A已经遍历过这个节点了 ,那么路径B可以按照路径A返回起点,所以可以形成环
1 | |

方法二:DFS
通过preI,preJ记录上一个已访问节点
1 | |


方法一:BFS
colors[next] == 1 - color说明访问过,而且颜色与当前颜色不同,不用加入队列
1 | |
方法二:DFS
1 | |
方法三:并查集
每个顶点i的邻居应该是在同一个集合里,如果i与邻居在一个集合,则不是二分图
遍历每一个顶点i,判断i与邻居是否在一个集合中,如果是则不是二分图返回false;如果顶点i不与邻居在同一个集合,那么将邻居合并到同一个集合
1 | |
剑指 Offer II 110. 所有路径

方法一:回溯
1 | |

方法一:DFS
1 | |
二进制矩阵中翻转最多一次使路径不连通

方法一:两次DFS
1 | |