Leetcode-200-岛屿数量

题目

image.png

题解

题解1:dfs

Java题解

class Solution {
    public int[][] next = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    public int rows;
    public int cols;
    boolean[][] visited;
    public int numIslands(char[][] grid) {
        if (grid.length==0 || grid[0].length==0) return 0;  // grid==null不行
        rows = grid.length;
        cols = grid[0].length;
        int res = 0;
        // boolean[][] visited = new boolean[rows][cols];
        visited = new boolean[rows][cols];
        for (int i=0; i=0 && i=0 && j

dfs不一定要用for循环和位置数组

// dfs
// 是否visit过,1的话就往下dfs,visit状态改变
// 或者1变为0?
class Solution {
    private boolean[][] visited;
    private int rows;
    private int cols;
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        int res = 0;
        rows = grid.length;
        cols = grid[0].length;
        visited = new boolean[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (!visited[i][j] && grid[i][j] == '1') {
                    dfs(grid, i, j);
                    res += 1;
                }
            }
        }
        return res;
    }
    private boolean valid(int i, int j) {
        if (i < 0 || i >= rows || j < 0 || j >= cols) {
            return false;
        }
        return true;
    }
    private void dfs(char[][] grid, int i, int j) {
        if (!valid(i, j) || visited[i][j]) {
            return;
        }
        if (grid[i][j] == '1') {
            visited[i][j] = true;
            dfs(grid, i + 1, j);
            dfs(grid, i - 1, j);
            dfs(grid, i, j + 1);
            dfs(grid, i, j - 1);
        }
        return;
    }
}

不用visited,把1改成0
但是
解决这个问题是可以不用建立 visited 数组,但有以下的知识点需要大家知道。
1、对于算法的输入而言,很多时候是介意修改输入的,除非题目就是要我们修改输入数据;
2、再者 visited 数组没有必要节约这个空间,现在空间越来越不值钱了,而且程序执行完成以后,空间可以回收。我们写算法的时候,应该力求时间复杂度最优,并且代码可读性强。

问清楚面试官,是否可以修改传来的 nums 数组!

// dfs
// 是否visit过,1的话就往下dfs,visit状态改变
// 或者1变为0?
class Solution {
    private int rows;
    private int cols;
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        int res = 0;
        rows = grid.length;
        cols = grid[0].length;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (grid[i][j] == '1') {
                    dfs(grid, i, j);
                    res += 1;
                }
            }
        }
        return res;
    }
    private boolean valid(int i, int j) {
        if (i < 0 || i >= rows || j < 0 || j >= cols) {
            return false;
        }
        return true;
    }
    private void dfs(char[][] grid, int i, int j) {
        if (!valid(i, j)) {
            return;
        }
        if (grid[i][j] == '1') {
            grid[i][j] = '0';
            dfs(grid, i + 1, j);
            dfs(grid, i - 1, j);
            dfs(grid, i, j + 1);
            dfs(grid, i, j - 1);
        }
        return;
    }
}
题解2:bfs:非递归

队列

// bfs
// 队列
// visited或是替换为0
class Pos{
    int i;
    int j;
    // public void position(int i, int j) {
    Pos(int i, int j) {
        this.i = i;
        this.j = j;
    }
}
class Solution {
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        // 坐标传递
        int rows = grid.length;
        int cols = grid[0].length;
        int res = 0;
        // Queue queue= new LinkedList();    // Linkedlist
        Queue queue= new LinkedList<>();
        // queue.add(new Pos(0, 0));
        // 队列为空是什么情况,怎么计数
        for (int r = 0; r < rows; r++) {
            for (int c = 0; c < cols; c++) {
                if (grid[r][c] == '1') {
                    res += 1;
                    queue.add(new Pos(r, c));
                    while (!queue.isEmpty()) {
                        Pos current = queue.poll();
                        int i = current.i;
                        int j = current.j;
                        if (valid(i, j, rows, cols)) {
                            if (grid[i][j] == '1') {
                                grid[i][j] = '0';
                                queue.add(new Pos(i + 1, j));
                                queue.add(new Pos(i - 1, j));
                                queue.add(new Pos(i, j + 1));
                                queue.add(new Pos(i, j - 1));
                            }
                        }
                    }
                }
            }
        }
        // while (!queue.isEmpty()) {
        //     Pos current = queue.poll();
        //     int i = current.i;
        //     int j = current.j;
        //     if (valid(i, j, rows, cols)) {
        //         if (grid[i][j] == '1') {
        //             grid[i][j] = '0';
        //             queue.add(new Pos(i + 1, j));
        //             queue.add(new Pos(i - 1, j));
        //             queue.add(new Pos(i, j + 1));
        //             queue.add(new Pos(i, j - 1));
        //         }
        //     }
        // }
        return res;
    }
    private boolean valid(int i, int j, int rows, int cols) {
        if (i < 0 || i >= rows || j < 0 || j >= cols) {
            return false;
        }
        return true;
    }
}
题解3:并查集

思路1
dfs遍历找与dummy不相连的1,dfs中把所有相连的1都与dummy连起来,所以有几个新的入口,就有几个岛屿

class UF {
    private int count;      // 连通分量
    private int[] parent;   // 树
    private int[] size;     // 树的重量
    public UF(int n) {
        this.count = n;
        parent = new int[n];
        size = new int[n];
        for (int i = 0; i < n; i++) {
            parent[i] = i;
            size[i] = 1;
        }
    }
    public int find(int x) {
        while (parent[x] != x) {
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }
    public void union(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP == rootQ) {
            return;
        }
        if (size[rootP] > size[rootQ]) {
            parent[rootQ] = rootP;
            size[rootP] += size[rootQ];
        } else {
            parent[rootP] = rootQ;
            size[rootQ] += size[rootP];
        }
        count--;
    }
    public boolean connected(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        return rootP == rootQ;
    }
    public int count() {
        return count;
    }
}
// 思路1
// dfs遍历找与dummy不相连的1,把1与dummy连起来,所以有几个新的入口,就有几个岛屿
class Solution {
    private int rows;
    private int cols;
    private UF uf;
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        rows = grid.length;
        cols = grid[0].length;
        // 把1的都连起来,找到几个1的入口就是res
        uf = new UF(rows * cols + 1);
        int res = 0;
        int dummy = rows * cols;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (grid[i][j] == '1' && !uf.connected(dummy, (i * cols + j))) {  // 是1,且与dummy不连接
                    // uf.union(i * j, dummy);
                    // 还是要用dfs去把与1连接的都连起来
                    dfs(grid, i, j, dummy);
                    res += 1;
                }
            }
        }
        return res;
    }
    private boolean valid(int i, int j) {
        if (i < 0 || i >= rows || j < 0 || j >= cols) {
            return false;
        }
        return true;
    }
    private void dfs(char[][] grid, int i, int j, int dummy) {
        if (!valid(i, j)) {
            return;
        }
        if (grid[i][j] == '1' && !uf.connected(dummy, (i * cols + j))) {
            uf.union(dummy, (i * cols + j));
            dfs(grid, i + 1, j, dummy);
            dfs(grid, i - 1, j, dummy);
            dfs(grid, i, j + 1, dummy);
            dfs(grid, i, j - 1, dummy);
        }
        return;
    }
}

思路2

class UF {
    private int count;      // 连通分量
    private int[] parent;   // 树
    private int[] size;     // 树的重量
    public UF(int n) {
        this.count = n;
        parent = new int[n];
        size = new int[n];
        for (int i = 0; i < n; i++) {
            parent[i] = i;
            size[i] = 1;
        }
    }
    public int find(int x) {
        while (parent[x] != x) {
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }
    public void union(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        if (rootP == rootQ) {
            return;
        }
        if (size[rootP] > size[rootQ]) {
            parent[rootQ] = rootP;
            size[rootP] += size[rootQ];
        } else {
            parent[rootP] = rootQ;
            size[rootQ] += size[rootP];
        }
        count--;
    }
    public boolean connected(int p, int q) {
        int rootP = find(p);
        int rootQ = find(q);
        return rootP == rootQ;
    }
    public int count() {
        return count;
    }
}
// 思路1
// 把0和dummy连接,把1的都连起来,最后计数连通分量-1,减去的1是指dummy那个
class Solution {
    private int rows;
    private int cols;
    private UF uf;
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        rows = grid.length;
        cols = grid[0].length;
        uf = new UF(rows * cols + 1);
        int dummy = rows * cols;
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                if (grid[i][j] == '0') {
                    uf.union(dummy, (i * cols + j));
                }
                // 向下向右遍历1的周边
                if (grid[i][j] == '1') {
                    if (valid(i + 1, j)) {   // 向下
                        if (grid[i + 1][j] == '1') {
                            uf.union((i * cols + j), ((i + 1) * cols + j));
                        }
                    }
                    if (valid(i, j + 1)) {
                        if (grid[i][j + 1] == '1') {
                            uf.union((i * cols + j), (i * cols + (j + 1)));
                        }
                    }
                }
            }
        }
        return uf.count() - 1;
    }
    private boolean valid(int i, int j) {
        if (i < 0 || i >= rows || j < 0 || j >= cols) {
            return false;
        }
        return true;
    }
}

参考

https://leetcode-cn.com/problems/number-of-islands/solution/dfs-bfs-bing-cha-ji-python-dai-ma-java-dai-ma-by-l/

image.png

你可能感兴趣的:(Leetcode-200-岛屿数量)