图的遍历 BFS DFS
如何不重复遍历所有节点?
BFS 借助队列,(和树的层次遍历很像)从某个节点开始,访问所有和他相接的点 => 继续往下
DFS 一条路走到黑
岛屿数量
力扣 200. 岛屿数量
dfs 深搜
遍历二维数组,只要 grid[i][j] = 1
,那么对于这个点来说,向上下左右四个方向扩散,只要遍历到的就算做同一个岛屿,同时grid[i][j] = 2
标记为遍历过。
java
class Solution {
public int numIslands(char[][] grid) {
int count = 0;
for(int i=0; i<grid.length; i++) {
for(int j=0; j<grid[0].length; j++) {
if(grid[i][j] == '1') {
count++;
dfs(grid, i, j);
}
}
}
return count;
}
public void dfs(char[][]grid, int x, int y) {
if(x<0 || y<0 || y>=grid[0].length || x>=grid.length || grid[x][y]!='1') {
return;
}
grid[x][y] = '2';
dfs(grid, x-1, y); //shang
dfs(grid, x+1, y);
dfs(grid, x, y-1);
dfs(grid, x, y+1);
}
}
bfs 广搜
- 特点
源点开始,一圈一圈向外遍历,像水的波纹。从近到远,由内而外 - 如何实现此种遍历呢? 用队列
源点进队
源点出队,距离为1的点入队
距离为1的点出队,距离为2的点入队能够保证队列中,距离的单调递增
java
class Solution {
public int numIslands(char[][] grid) {
int count = 0;
for(int i=0; i<grid.length; i++) {
for(int j=0; j<grid[0].length; j++) {
if(grid[i][j] == '1') {
count++;
bfs(grid, i, j);
}
}
}
return count;
}
public void bfs(char[][]grid, int x, int y) {
Queue<int[]> list = new LinkedList<>();
list.add(new int[]{x,y});
int i=0, j=0;
while(!list.isEmpty()) {
int[] cur = list.remove();
i = cur[0];
j = cur[1];
if(i>=0 && i<grid.length && j>=0 && j<grid[0].length && grid[i][j] == '1') {
grid[i][j] = '2';
list.add(new int[] { i + 1, j });
list.add(new int[] { i - 1, j });
list.add(new int[] { i, j + 1 });
list.add(new int[] { i, j - 1 });
}
}
}
}
Kama 99.岛屿数量
dfs
- 与力扣200没有区别,但是要学习输入输出方法
java
import java.util.*;
class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int M = sc.nextInt();
int[][]grid = new int[N][M];
for(int i=0; i<N; i++) {
for(int j=0; j<M; j++) {
grid[i][j] = sc.nextInt();
}
}
int count = 0;
for(int i=0; i<N; i++) {
for(int j=0; j<M; j++) {
if(grid[i][j] == 1) {
count++;
dfs(grid, i, j);
}
}
}
System.out.println(count);
}
public static void dfs(int[][] grid, int x, int y){
if(x<0 || y<0 || y>=grid[0].length || x>=grid.length || grid[x][y]!=1) {
return;
}
grid[x][y] = 2;
dfs(grid, x-1, y); //shang
dfs(grid, x+1, y);
dfs(grid, x, y-1);
dfs(grid, x, y+1);
}
}
100.岛屿的最大面积
- 力扣 695
这里使用了数组 int[] di = {0, 0, 1, -1}; int[] dj = {1, -1, 0, 0};
表示方向,更直观。
java
class Solution {
public int maxAreaOfIsland(int[][] grid) {
int ans = 0;
for(int i=0; i<grid.length; i++) {
for(int j=0; j<grid[0].length; j++) {
if(grid[i][j] == 1) {
ans = Math.max(ans, dfs(grid, i, j));
}
}
}
return ans;
}
public int dfs(int[][] grid, int x, int y) {
if(x<0 || y<0 || x>=grid.length || y>=grid[0].length || grid[x][y]!=1) {
return 0;
}
grid[x][y] = 2;
int[] di = {0, 0, 1, -1};
int[] dj = {1, -1, 0, 0};
int ans = 1;
for(int index=0; index<4; index++) {
int next_i = x + di[index];
int next_j = y + dj[index];
ans += dfs(grid, next_i, next_j);
}
return ans;
}
}