文章目录
DFS和BFS的区别
之前在二叉树那个部分写过一篇关于深搜和广搜的介绍和二叉树中的应用,可以参考这篇文章二叉树中深搜广搜的介绍。今天来整理一下在图论中深搜和广搜的应用。
首先,说一下二者的区别。
- DFS是可一个方向去搜,不到黄河不回头,直到遇到绝境了,搜不下去了,再换方向(换方向的过程就涉及到了回溯)
- BFS先把本节点所连接的所有节点遍历一遍,走到下一个节点的时候,再把连接节点的所有节点遍历一遍,搜索方向更像是广度,四面八方的搜索过程。
代码框架
DFS
1、确认递归函数以及参数
2、确认终止条件
3、处理当前节点
BFS
用队列或者栈去实现,我个人喜欢使用队列来实现
练习
class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> allPathsSourceTarget(int[][] graph) {
path.add(0);
backtracking(0, graph);
return result;
}
private void backtracking(int startIndex, int[][] graph) {
if (startIndex == graph.length - 1) {
result.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < graph[startIndex].length; ++i) {
path.add(graph[startIndex][i]);
backtracking(graph[startIndex][i], graph);
path.removeLast();
}
}
}
class Solution {
boolean[][] used;
int[][] direction = {
{0, 1}, //向右一步
{0, -1}, //向左一步
{-1, 0}, //向上一步
{1, 0} //向下一步
};
public int numIslands(char[][] grid) {
int count = 0;
used = new boolean[grid.length][grid[0].length];
for (int i = 0; i < grid.length; ++i) {
for (int j = 0; j < grid[0].length; ++j) {
if (grid[i][j] == '1' && used[i][j] == false) {
count += 1;
// dfs(grid, i, j);
bfs(grid, i, j);
}
}
}
return count;
}
private void dfs(char[][] grid, int x, int y) {
if (grid[x][y] == '0' || used[x][y] == true) {
return;
}
used[x][y] = true;
for (int i = 0; i < direction.length; ++i) {
int nextX = x + direction[i][0];
int nextY = y + direction[i][1];
if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) {
continue;
}
dfs(grid, nextX, nextY);
}
}
private void bfs(char[][] grid, int x, int y) {
Deque<int[]> queue = new ArrayDeque<>();
queue.offer(new int[]{x, y});
used[x][y] = true;
while (!queue.isEmpty()) {
int[] pos = queue.poll();
int m = pos[0];
int n = pos[1];
for (int i = 0; i < direction.length; ++i) {
int nextX = m + direction[i][0];
int nextY = n + direction[i][1];
if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) {
continue;
}
if (used[nextX][nextY] == false && grid[nextX][nextY] == '1') {
used[nextX][nextY] = true;
queue.offer(new int[]{nextX, nextY});
}
}
}
}
}
class Solution {
boolean[][] used;
int count;
int[][] direction = {
{-1, 0}, //向上
{1, 0}, //向下
{0, 1}, //向右
{0, -1} //向左
};
public int maxAreaOfIsland(int[][] grid) {
int area = 0;
used = new boolean[grid.length][grid[0].length];
for (int i = 0; i < grid.length; ++i) {
for (int j = 0; j < grid[0].length; ++j) {
if (used[i][j] == false && grid[i][j] == 1) {
count = 0;
bfs(grid, i, j);
area = Math.max(area, count);
}
}
}
return area;
}
private void dfs(int[][] grid, int x, int y) {
if (used[x][y] == true || grid[x][y] == 0) {
return;
}
count += 1;
used[x][y] = true;
for (int i = 0; i < 4; ++i) {
int nextX = x + direction[i][0];
int nextY = y + direction[i][1];
if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) {
continue;
}
dfs(grid, nextX, nextY);
}
}
private void bfs(int[][] grid, int x, int y) {
Deque<int[]> queue = new ArrayDeque<>();
queue.offer(new int[]{x, y});
used[x][y] = true;
count += 1;
while (!queue.isEmpty()) {
int[] pos = queue.poll();
int m = pos[0];
int n = pos[1];
for (int i = 0; i < 4; ++i) {
int nextX = m + direction[i][0];
int nextY = n + direction[i][1];
if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) {
continue;
}
if (used[nextX][nextY] == false && grid[nextX][nextY] == 1) {
used[nextX][nextY] = true;
count += 1;
queue.offer(new int[]{nextX, nextY});
}
}
}
}
}
class Solution {
int count = 0;
int[][] dir = {
{0, 1},//向右
{0, -1},//向左
{1, 0},//向下
{-1, 0}//向上
};
public int numEnclaves(int[][] grid) {
for (int i = 0; i < grid.length; ++i) {
if (grid[i][0] == 1) {
dfs(grid, i, 0);
}
if (grid[i][grid[0].length - 1] == 1) {
dfs(grid, i, grid[0].length - 1);
}
}
for (int j = 1; j < grid[0].length - 1; ++j) {
if (grid[0][j] == 1) {
dfs(grid, 0, j);
}
if (grid[grid.length - 1][j] == 1) {
dfs(grid, grid.length - 1, j);
}
}
count = 0;
for (int i = 1; i < grid.length - 1; ++i) {
for (int j = 1; j < grid[0].length - 1; ++j) {
if (grid[i][j] == 1) {
dfs(grid, i, j);
}
}
}
return count;
}
private void dfs(int[][] grid, int x, int y) {
if (grid[x][y] == 0) {
return;
}
grid[x][y] = 0;
++count;
for (int i = 0; i < 4; ++i) {
int nextX = x + dir[i][0];
int nextY = y + dir[i][1];
if (nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length) {
continue;
}
dfs(grid, nextX, nextY);
}
}
}
class Solution {
int[][] dir = {
{0, 1},
{0, -1},
{1, 0},
{-1, 0}
};
public void solve(char[][] board) {
for (int i = 0; i < board.length; ++i) {
if (board[i][0] == 'O') {
dfs(board, i, 0);
}
if (board[i][board[0].length - 1] == 'O') {
dfs(board, i, board[0].length - 1);
}
}
for (int j = 1; j < board[0].length - 1; ++j) {
if (board[0][j] == 'O') {
dfs(board, 0, j);
}
if (board[board.length - 1][j] == 'O') {
dfs(board, board.length - 1, j);
}
}
for (int i = 0; i < board.length; ++i) {
for (int j = 0; j < board[0].length; ++j) {
if (board[i][j] == 'A') {
board[i][j] = 'O';
}
else if (board[i][j] == 'O') {
board[i][j] = 'X';
}
}
}
}
private void dfs(char[][] board, int x, int y) {
if (board[x][y] == 'X') {
return;
}
board[x][y] = 'A';
for (int i = 0; i < 4; ++i) {
int nextX = x + dir[i][0];
int nextY = y + dir[i][1];
if (nextX < 0 || nextY < 0 || nextX >= board.length || nextY >= board[0].length) {
continue;
}
if (board[nextX][nextY] != 'O') {
continue;
}
dfs(board, nextX, nextY);
}
}
}
class Solution {
int[][] direction = {
{1, 0},
{-1, 0},
{0, 1},
{0, -1}
};
boolean[][][] visited;
public List<List<Integer>> pacificAtlantic(int[][] heights) {
List<List<Integer>> result = new ArrayList<>();
visited = new boolean[heights.length][heights[0].length][2];
for (int i = 0; i <heights.length; ++i) {
visited[i][heights[0].length - 1][0] = true;
visited[i][0][1] = true;
dfs(heights, i, heights[0].length - 1, 0);
dfs(heights, i, 0, 1);
}
for (int j = 0; j < heights[0].length; ++j) {
visited[heights.length - 1][j][0] = true;
visited[0][j][1] = true;
dfs(heights, heights.length - 1, j, 0);
dfs(heights, 0, j, 1);
}
for (int i = 0; i < heights.length; ++i) {
for (int j = 0; j < heights[0].length; ++j) {
if (visited[i][j][0] == true && visited[i][j][1] == true) {
result.add(Arrays.asList(i, j));
}
}
}
return result;
}
//sign表示哪条河流,太平洋为1,大西洋为0
private void dfs(int[][] heights, int x, int y, int sign) {
for (int i = 0; i < 4; ++i) {
int nextX = x + direction[i][0];
int nextY = y + direction[i][1];
if (nextX < 0 || nextY < 0 || nextX >= heights.length || nextY >= heights[0].length) {
continue;
}
//逆流而上,从低的地方找高的地方
if (heights[nextX][nextY] < heights[x][y] || visited[nextX][nextY][sign]) {
continue;
}
visited[nextX][nextY][sign] = true;
dfs(heights, nextX, nextY, sign);
}
}
}