深度优先搜索 DFS

深度优先搜索

如图所示,深度优先搜索DFS对新节点立即执行搜索,因此新节点都向下一层。
而广度优先搜索BFS先用队列存储新节点,等当前层的新节点都搜索完毕之后再搜索下一层节点。
在这里插入图片描述
图片链接

leetcode695

分析

使用2个函数。主函数统计比较每块岛屿的面积,子函数通过深度优先搜索计算每块岛屿的面积。
深度优先搜索是相对于广度优先搜索而言的。广度优先搜索考虑层级关系,

每块土地都只会被归纳到1个岛屿,被统计1次。因此为了防止重复计算,将统计过的土地置为0.

源码

class Solution {
    int[][] directions = {{1,0}, {-1,0},{0,1}, {0,-1}}; // 预定义的四个方向

    public int maxAreaOfIsland(int[][] grid) {
        int m = grid.length;
        int n = grid[0].length;

        int maxArea = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    int curArea = dfs(grid, i, j); // 计算当前岛屿的大小
                    maxArea = Math.max(maxArea, curArea);
                }
            }
        }
        return maxArea;
    }

    private int dfs(int[][] grid, int curI, int curJ) {
        if (curI < 0 || curI >= grid.length || curJ < 0 || curJ >= grid[0].length || grid[curI][curJ] == 0) {
            return 0; // 参数校验
        }
        int curArea = 1;
        grid[curI][curJ] = 0; // 防止重复计算
        for (int i = 0; i < 4; i++) {
            int nextI = curI + directions[i][0];
            int nextJ = curJ + directions[i][1];
            curArea += dfs(grid, nextI, nextJ);
        }
        return curArea;
    }
}

leetcode547

分析

矩阵是对称矩阵。每个城市必定与自己相连,因此主对角线元素必定为1.

源码

class Solution {
    public int findCircleNum(int[][] isConnected) {
        int provinces = 0;
        boolean[] visited = new boolean[isConnected.length];
        for (int i = 0; i < isConnected.length; i++) {
            if (!visited[i]) {
                dfs(visited, isConnected, i);
                provinces++;
            }
        }
        return provinces;
    }

    private void dfs(boolean[] visited, int[][] isConnected, int cityIdx) {
        visited[cityIdx] = true;
        for (int i = 0; i < isConnected.length; i++) {
        	// 标记与当前城市同省的其他城市
            if (isConnected[cityIdx][i] ==1 && !visited[i]) {
                dfs(visited, isConnected, i);
            }
        }
    }
}

leetcode417

分析

统计网格流向2个大洋比较复杂。可以反过来,统计2个大洋逆流而上能够到达的网格。2个大洋都能逆流到达的网格就是能够流向大洋的。

源码

class Solution {
    int[][] directions = {{1,0}, {-1,0},{0,1}, {0,-1}};

    public List<List<Integer>> pacificAtlantic(int[][] heights) {
        int m = heights.length;
        int n = heights[0].length;

        boolean[][] pacific = new boolean[m][n]; // 太平洋逆流而上能够到达的网格
        boolean[][] atlantic = new boolean[m][n]; // 大西洋逆流而上能够到达的网格
        for (int i = 0; i < m; i++) {
            dfs(pacific, heights, i, 0);
            dfs(atlantic, heights, i, n - 1);
        }

        for (int j = 0; j < n; j++) {
            dfs(pacific, heights, 0, j);
            dfs(atlantic, heights, m - 1, j);
        }
        // 对于heights[0][0],pacific会重复访问1次。对于heights[m-1][n-1],atlantic会重复访问1次。
     
        List<List<Integer>> res = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (pacific[i][j] && atlantic[i][j]) {
                    res.add(List.of(i, j));
                }
            }
        }
        return res;
    }

    private void dfs(boolean[][] ocean, int[][] heights, int curI, int curJ) {
        if (ocean[curI][curJ]) {
            return;
        }
        ocean[curI][curJ] = true;
        for (int i = 0; i < 4; i++) {
            int nextI = curI + directions[i][0];
            int nextJ = curJ + directions[i][1];
            if (nextI >= 0 && nextI < heights.length && nextJ >= 0 && nextJ < heights[0].length && heights[nextI][nextJ] >= heights[curI][curJ]) {
                dfs(ocean, heights, nextI, nextJ);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值