【图论】深度优先搜索(DFS)和广度优先搜索(BFS)学习

文章介绍了深度优先搜索(DFS)和广度优先搜索(BFS)的区别,通过实际编程示例展示了在解决力扣网上的几个问题时如何运用这两种搜索方法,如路径查找、岛屿计数和区域面积计算等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DFS和BFS的区别

之前在二叉树那个部分写过一篇关于深搜和广搜的介绍和二叉树中的应用,可以参考这篇文章二叉树中深搜广搜的介绍。今天来整理一下在图论中深搜和广搜的应用。

首先,说一下二者的区别。

  • DFS是可一个方向去搜,不到黄河不回头,直到遇到绝境了,搜不下去了,再换方向(换方向的过程就涉及到了回溯)
  • BFS先把本节点所连接的所有节点遍历一遍,走到下一个节点的时候,再把连接节点的所有节点遍历一遍,搜索方向更像是广度,四面八方的搜索过程。

代码框架

DFS

1、确认递归函数以及参数

2、确认终止条件

3、处理当前节点

BFS

用队列或者栈去实现,我个人喜欢使用队列来实现

练习

力扣797题

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();
        }
    }
}

力扣200题

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});
                }
            }
        }
    }
}

力扣695题

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});
                }
            }
        }
    }
}

力扣1020题

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);
        }
    }
}

力扣130题

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);
        }
    }
}

力扣417题

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);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值