leetcode算法基础 第六天 深搜/广搜

这篇博客探讨了深度优先搜索(DFS)和广度优先搜索(BFS)在解决岛屿数量和省份数量问题上的应用。通过实例展示了如何使用DFS和BFS进行图遍历,以及如何利用并查集优化解决方案。文章还提到了这两种算法在实际问题中的转换和优化策略。
摘要由CSDN通过智能技术生成

200. 岛屿数量

题目
这道题是一道简单的深搜题,首先双层遍历找到第一个’1’所在的位置,岛屿数加1,然后开始深搜,并将所有走过的地方标位’0’,以此类推,直到所有的位置都为’0’。

public int numIslands(char[][] grid) {
    if (grid == null || grid.length == 0) {
        return 0;
    }
    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(i, j, grid);
            }
        }
    }
    return count;
}

public void dfs(int i, int j, char[][] grid){
    if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == '0') return;
    grid[i][j] = '0';
    dfs(i - 1, j, grid);
    dfs(i + 1, j, grid);
    dfs(i, j - 1, grid);
    dfs(i, j + 1, grid);
}

广搜的思想也很简单,找到第一个’1’入队列,并将值改为’0’,每次将距离为1的四个方向的’1’入队,以此类推直到队列为空。

public int numIslands1(char[][] grid){
    int count = 0;
    int[][] vector = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
    Queue<int[]> queue = new LinkedList<>();
    for (int i = 0; i < grid.length; i++){
        for (int j = 0; j < grid[0].length; j++){
            if(grid[i][j] == '1'){
                count++;
                grid[i][j] = '0';
                queue.add(new int[]{i, j});
                while(!queue.isEmpty()){
                    int[] n = queue.poll();
                    for (int[] v : vector) {
                        int nr = n[0] + v[0];
                        int nc = n[1] + v[1];
                        if (nr >= 0 && nc >= 0 && nr < grid.length && nc < grid[0].length && grid[nr][nc] == '1') {
                            grid[nr][nc] = '0';
                            queue.add(new int[]{nr, nc});
                        }
                    }
                }
            }
        }
    }
    return count;
}

547. 省份数量**

题目
深度遍历DFS,设置一个visited记录数组,每次跳到连通城市,找还没有访问过的城市。A-B,B-C, A-D 优先往下找。

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

public void dfs(int[][] isConnected, boolean[] visited, int provinces, int i) {
    for (int j = 0; j < provinces; j++) {
        if (isConnected[i][j] == 1 && !visited[j]) {
            visited[j] = true;
            dfs(isConnected, visited, provinces, j);
        }
    }
}

广度遍历,优先找A的所有连通城市,再找连通城市的其他连通城市。主要思想都是设置一个visited函数。

public int findCircleNum1(int[][] isConnected) {
    int provinces = isConnected.length;
    boolean[] visited = new boolean[provinces];
    int circles = 0;
    Queue<Integer> queue = new LinkedList<Integer>();
    for (int i = 0; i < provinces; i++) {
        if (!visited[i]) {
            queue.offer(i);
            while (!queue.isEmpty()) {
                int j = queue.poll();
                visited[j] = true;
                for (int k = 0; k < provinces; k++) {
                    if (isConnected[j][k] == 1 && !visited[k]) {
                        queue.offer(k);
                    }
                }
            }
            circles++;
        }
    }
    return circles;
}

并查集,find和union函数可以当做模板背诵。

public int findCircleNum2(int[][] isConnected) {
    int provinces = isConnected.length;
    int[] parent = new int[provinces];
    for (int i = 0; i < provinces; i++) {
        parent[i] = i;
    }
    for (int i = 0; i < provinces; i++) {
        for (int j = i + 1; j < provinces; j++) {
            if (isConnected[i][j] == 1) {
                union(parent, i, j);
            }
        }
    }
    int circles = 0;
    for (int i = 0; i < provinces; i++) {
        if (parent[i] == i) {
            circles++;
        }
    }
    return circles;
}

//让index1的父节点指向index2的父节点
public void union(int[] parent, int index1, int index2) {
    parent[find(parent, index1)] = find(parent, index2);
}

public int find(int[] parent, int index) {
    //不是父节点,找父节点
    if (parent[index] != index) {
        parent[index] = find(parent, parent[index]);
    }
    return parent[index];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值