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<rows; i++){
            for (int j=0; j<cols; j++){
                // if (helper(grid, visited, i, j))
                //     res += 1;
                if (!visited[i][j] && grid[i][j]=='1'){  //
                    helper(grid, i, j);
                    res += 1;
                }
            }
        }
        return res;
    }
    private boolean isValid(int i, int j){
        if (i>=0 && i<rows && j>=0 && j<cols)
            return true;
        return false;
    }
    private void helper(char[][] grid, int i, int j){
        if (!isValid(i, j) || visited[i][j]) return;
        if (grid[i][j] == '1'){ 
            visited[i][j] = true; 
            for (int m=0; m<4; m++){
                helper(grid, i+next[m][0], j+next[m][1]);
            }
            // visited[i][j] = false;  
        }
        return;
    }
}

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<Pos> queue= new LinkedList<new Pos()>();    // Linkedlist
        Queue<Pos> 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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,245评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,749评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,960评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,575评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,668评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,670评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,664评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,422评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,864评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,178评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,340评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,015评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,646评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,265评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,494评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,261评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,206评论 2 352