Búsqueda --- profundidad primera búsqueda

La búsqueda de profundidad atraviesa un nuevo nodo inmediatamente cuando se obtiene un nuevo nodo.
Comenzando desde un nodo, cuando se usa DFS para atravesar un gráfico, los nodos que se pueden atravesar son accesibles desde el nodo inicial. DFS se usa a menudo para resolver este problema. Problemas de accesibilidad.
Deben tenerse en cuenta los siguientes problemas cuando el programa implementa DFS:

Pila: use la pila para guardar la información del nodo actual y continúe atravesando el nodo actual cuando atraviese el nuevo nodo. Puedes usar una pila recursiva.
Marcado: al igual que con BFS, también es necesario marcar los nodos que se han recorrido.

1. Encuentra el área conectada más grande

/*
    * 题目:最大连通的面积
    * */
    public int maxAreaOfIsland(int[][] grid) {
        int m = grid.length, n = grid[0].length;
        int book[][] = new int[m][n];
        int maxArea = 0;
        int direction[][] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                maxArea = Math.max(maxArea, connectArea(grid, i, j, book, direction));
            }
        }
        return maxArea;
    }

    private int connectArea(int[][] grid, int i, int j, int[][] book, int[][] direction) {
        if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) return 0;
        if (book[i][j] == 1 || grid[i][j] == 0) return 0;
        book[i][j] = 1;
        int count = 1;
        for (int k = 0; k < direction.length; k++) {
            int x = i + direction[k][0], y = j + direction[k][1];
            count += connectArea(grid, x, y, book, direction);
        }
        return count;
    }

2. Número de componentes conectados en la matriz.

/*
    *矩阵中的连通分量数目
    * */
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0) {
            return 0;
        }
        int m = grid.length, n = grid[0].length;
        int count = 0;
        int direction[][] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == '1') {
                    count += 1;
                    connectArea1(grid, i, j, direction);
                }
            }
        }
        return count;
    }

    private void connectArea1(char[][] grid, int i, int j, int[][] direction) {
        if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) return;
        if (grid[i][j] == '0') return;
        grid[i][j] = '0';
        for (int k = 0; k < direction.length; k++) {
            int x = i + direction[k][0], y = j + direction[k][1];
            connectArea1(grid, x, y, direction);
        }
        return;
    }

3. Número de componentes conectados de la relación de amistad.

 /*
    * 好友关系的连通分量数目
    * 题目描述:好友关系可以看成是一个无向图,例如第 0 个人与第 1 个人是好友,那么 M[0][1] 和 M[1][0] 的值都为 1。
    * 解析:注意匹配规则!
    * */
    public int findCircleNum(int[][] M) {
        if (M == null || M.length == 0) {
            return 0;
        }
        int m = M.length, n = M[0].length;
        int count = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j <= i; j++) {
                if (M[i][j] == 1) {
                    count += 1;
                    connectArea2(M, i, j);
                }
            }
        }
        return count;
    }

    private void connectArea2(int[][] M, int i, int j) {
        if (i < 0 || j < 0 || i >= M.length || j > M[0].length) return;
        if (M[i][j] == 0 && M[j][i] == 0) return;
        M[i][j] = 0;
        M[j][i] = 0;
        for (int k = 0; k < M.length; k++) {
            connectArea2(M, i, k);
            connectArea2(M, k, j);
        }
        return;
    }

4. Rellene el área cerrada

 /*
    * 填充封闭区域
    * 题目描述:使被 'X' 包围的 'O' 转换为 'X'。
    * */
    public void solve(char[][] board) {
        if (board == null || board.length == 0) {
            return;
        }
        int m = board.length, n = board[0].length;
        int direction[][] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
        for (int i = 0; i < m; i++) {
            connectArea3(board, i, 0, direction);
            connectArea3(board, i, n - 1, direction);
        }
        for (int j = 0; j < n; j++) {
            connectArea3(board, 0, j, direction);
            connectArea3(board, m - 1, j, direction);
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == 'O') {
                    board[i][j] = 'X';
                }
                if (board[i][j] == 'Z') {
                    board[i][j] = 'O';
                }
            }
        }
    }

    private void connectArea3(char[][] grid, int i, int j, int[][] direction) {
        if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) return;
        if (grid[i][j] != 'O') return;
        grid[i][j] = 'Z';
        for (int k = 0; k < direction.length; k++) {
            int x = i + direction[k][0], y = j + direction[k][1];
            connectArea3(grid, x, y, direction);
        }
        return;
    }

5. Las regiones accesibles del Pacífico y el Atlántico

/*
    * 能到达的太平洋和大西洋的区域
    * 左边和上边是太平洋,右边和下边是大西洋,内部的数字代表海拔,海拔高的地方的水能够流到低的地方,求解水能够流到太平洋和大西洋的所有位置。
    * */
    public List<List<Integer>> pacificAtlantic(int[][] matrix) {
        List<List<Integer>> list = new LinkedList<>();
        if (matrix == null || matrix.length == 0) return list;
        int m = matrix.length, n = matrix[0].length;
        int direction[][] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
        int bookT[][] = new int[m][n];//表示太平洋可达性记录
        int bookD[][] = new int[m][n];//表示大西洋可达性记录
        for (int i = 0; i < m; i++) {
            arrive(matrix, i, 0, direction, bookT);
            arrive(matrix, i, n - 1, direction, bookD);
        }
        for (int j = 0; j < n; j++) {
            arrive(matrix, 0, j, direction, bookT);
            arrive(matrix, m - 1, j, direction, bookD);
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (bookD[i][j] == 1 && bookT[i][j] == 1) {
                    List<Integer> curElem = new LinkedList<>(Arrays.asList(i, j));
                    list.add(curElem);
                }
            }
        }
        return list;
    }

    public void arrive(int[][] matrix, int i, int j, int direction[][], int book[][]) {
        if (book[i][j] != 0) return;
        book[i][j] = 1;//代表该点可达
        for (int k = 0; k < direction.length; k++) {
            int x = i + direction[k][0];
            int y = j + direction[k][1];
            if (x < 0 || x >= matrix.length || y < 0 || y >= matrix[0].length) continue;
            if (matrix[x][y] >= matrix[i][j]) {
                arrive(matrix, x, y, direction, book);
            }
        }
    }

Referencia: github : solución del problema CyC2018

184 artículos originales publicados · Me gusta 60 · Visitas 160,000+

Supongo que te gusta

Origin blog.csdn.net/StubbornAccepted/article/details/103079819
Recomendado
Clasificación