Leetcode - Number of Islands

Leetcode - Number of Islands_第1张图片
Screenshot from 2016-02-27 23:58:44.png

My code:

public class Solution {
    private int count = 0;
    private int width = 0;
    private int height = 0;
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0)
            return 0;
        boolean[][] isVisited = new boolean[grid.length][grid[0].length];
        width = grid[0].length;
        height = grid.length;
        int count = 0;
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (!isVisited[i][j] && grid[i][j] == '1') {
                    count++;
                    dfs(grid, isVisited, i, j);
                }
            }
        }
        return count;
    }
    
    private void dfs(char[][] grid, boolean[][] isVisited, int i, int j) {
        if (!isValidLocation(i, j) || isVisited[i][j] || grid[i][j] == '0')
            return;
        isVisited[i][j] = true;
        dfs(grid, isVisited, i - 1, j);
        dfs(grid, isVisited, i + 1, j);
        dfs(grid, isVisited, i, j - 1);
        dfs(grid, isVisited, i, j + 1);
    }
    
    private boolean isValidLocation(int i, int j) {
        if (i < 0 || i >= height)
            return false;
        else if (j < 0 || j >= width)
            return false;
        else
            return true;
    }
}

这是dfs版本。

这道题目可以用三种方法写。
dfs, bfs, union-find
花了挺多时间。

dfs:
My code:

public class Solution {
    private int row = 0;
    private int col = 0;
    private int[][] dir = new int[][]{{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        
        int counter = 0;
        this.row = grid.length;
        this.col = grid[0].length;
        boolean[][] mark = new boolean[grid.length][grid[0].length];
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (!mark[i][j] && grid[i][j] == '1') {
                    counter++;
                    dfs(i, j, grid, mark);
                }
            }
        }
        
        return counter;
    }
    
    private void dfs(int i, int j, char[][] grid, boolean[][] mark) {
        mark[i][j] = true;
        for (int k = 0; k < 4; k++) {
            int curr_r = i + dir[k][0];
            int curr_c = j + dir[k][1];
            if (check(curr_r, curr_c) && !mark[curr_r][curr_c] && grid[curr_r][curr_c] == '1') {
                dfs(curr_r, curr_c, grid, mark);
            }
        }
    }
    
    private boolean check(int i, int j) {
        if (i < 0 || i >= row || j < 0 || j >= col) {
            return false;
        }
        return true;
    }
    
    public static void main(String[] args) {
        Solution test = new Solution();
        char[][] input = new char[4][5];
        input[0] = "11110".toCharArray();
        input[1] = "11010".toCharArray();
        input[2] = "11000".toCharArray();
        input[3] = "00000".toCharArray();
        int ret = test.numIslands(input);
        System.out.println(ret);
    }
}

bfs:
My code:

public class Solution {
    private int row = 0;
    private int col = 0;
    private int[][] dir = new int[][]{{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
    
    private class Pair {
        int x;
        int y;
        Pair(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        
        this.row = grid.length;
        this.col = grid[0].length;
        
        boolean[][] mark = new boolean[this.row][this.col];
        int counter = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (grid[i][j] == '1' && !mark[i][j]) {
                    visit(i, j, mark, grid);
                    counter++;
                }
            }
        }
        
        return counter;        
    }
    
    private void visit(int i, int j, boolean[][] mark, char[][] grid) {
        Queue q = new LinkedList();
        q.offer(new Pair(i, j));
        while (!q.isEmpty()) {
            Pair curr = q.poll();
            mark[curr.x][curr.y] = true;
            for (int k = 0; k < 4; k++) {
                int curr_r = curr.x + dir[k][0];
                int curr_c = curr.y + dir[k][1];
                if (check(curr_r, curr_c) && grid[curr_r][curr_c] == '1' && !mark[curr_r][curr_c]) {
                    q.offer(new Pair(curr_r, curr_c));
                }
            }
        }
    }
    
    
    private boolean check(int i, int j) {
        if (i < 0 || i >= row || j < 0 || j >= col) {
            return false;
        }
        return true;
    }
    
}

这个bfs老是超时,我也不知道为什么,暂且不管了。
其实这里的bfs和dfs差不多,也得用 一个容器来标志每个节点的状态。防止重复。

下面是 Union-Find

My code:

public class Solution {
    private int row = 0;
    private int col = 0;
    private int[][] dir = new int[][]{{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
    private int[] id;
    private int[] size;
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        
        this.row = grid.length;
        this.col = grid[0].length;
        id = new int[row * col];
        size = new int[row * col];
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                id[i * col + j] = i * col + j;
                size[i * col + j] = 1;
            }
        }
        
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (grid[i][j] == '1') {
                    visit(i, j, grid);
                }
            }
        }
        
        int counter = 0;
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (grid[i][j] == '1' && i * col + j == this.find(i * col + j)) {
                    counter++;
                }
            }
        }
        
        return counter;
    }
    
    private void visit(int i, int j, char[][] grid) {
        int index = i * col + j;
        for (int k = 0; k < 4; k++) {
            int curr_r = i + dir[k][0];
            int curr_c = j + dir[k][1];
            if (check(curr_r, curr_c) && grid[curr_r][curr_c] == '1') {
                union(index, curr_r * col + curr_c);
            }
        }
    }
    
    private boolean check(int i, int j) {
        if (i < 0 || i >= row || j < 0 || j >= col) {
            return false;
        }
        return true;
    }
    
    private int find(int i) {
        if (id[i] == i) {
            return i;
        }
        else {
            int ret = find(id[i]);
            id[i] = ret;
            return ret;
        }
    }
    
    private void union(int i, int j) {
        int left = find(i);
        int right = find(j);
        if (left == right) {
            return;
        }
        else {
            if (size[left] < size[right]) {
                id[left] = right;
                size[right] += size[left];
            }
            else {
                id[right] = left;
                size[left] += size[right];
            }
        }
    }
    
    public static void main(String[] args) {
        Solution test = new Solution();
        char[][] input = new char[4][5];
        input[0] = "11110".toCharArray();
        input[1] = "11010".toCharArray();
        input[2] = "11000".toCharArray();
        input[3] = "00000".toCharArray();
        int ret = test.numIslands(input);
        System.out.println(ret);
    }
}

趁着这个机会复习了下 Union find or called Disjoint Set
reference:
http://www.geeksforgeeks.org/disjoint-set-data-structures-java-implementation/

重点就是记住, find 的时候呢需要 compress path
然后多用一个size数组,当两个树merge的时候,小树得merge into 大树

Anyway, Good luck, Richardo! -- 09/09/2016

My code:

public class Solution {
    private int row = 0;
    private int col = 0;
    private int[][] dir = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
    public int numIslands(char[][] grid) {
        if (grid == null || grid.length == 0 || grid[0].length == 0) {
            return 0;
        }
        this.row = grid.length;
        this.col = grid[0].length;
        UnionFind uf = new UnionFind(this.row, this.col);
        
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                if (grid[i][j] == '1') {
                    int id = uf.add(i, j);
                    for (int k = 0; k < 4; k++) {
                        int next_x = i + dir[k][0];
                        int next_y = j + dir[k][1];
                        if (check(next_x, next_y) && grid[next_x][next_y] == '1') {
                            int next_id = uf.find(next_x, next_y);
                            if (next_id > 0) {
                                uf.union(i, j, next_x, next_y);
                            }
                        }
                    }
                }
            }
        }
        
        return uf.counter;
    }
    
    private boolean check(int i, int j) {
        if (i < 0 || i >= row || j < 0 || j >= col) {
            return false;
        }
        else {
            return true;
        }
    }
}

class UnionFind {
    int[] ids;
    int[] sz;
    int row;
    int col;
    int counter;
    UnionFind(int row, int col) {
        this.row = row;
        this.col = col;
        ids = new int[row * col + 1];
        sz = new int[row * col + 1];
        counter = 0;
    }
    
    int add(int i, int j) {
        int id = getId(i, j);
        ids[id] = id;
        counter++;
        return id;
    }
    
    int find(int i, int j) {
        return find(getId(i, j));
    }
    
    int find(int id) {
        if (ids[id] == id) {
            return id;
        }
        else {
            int ret = find(ids[id]);
            ids[id] = ret;
            return ret;
        }
    }

    void union(int i1, int j1, int i2, int j2) {
        int id1 = find(i1, j1);
        int id2 = find(i2, j2);
        if (id1 == id2) {
            return;
        }
        else {
            counter--;
            if (sz[id1] > sz[id2]) {
                ids[id2] = id1;
                sz[id1] += sz[id2];
            }
            else {
                ids[id1] = id2;
                sz[id2] += sz[id1];
            }
        }
    }
    
    int getId(int i, int j) {
        return i * col + j + 1;
    }
}

采用了一种比较新的方法写 Union Find
利用一个counter来记录 独立部分的个数
ids[id] = i * col + j + 1;

Anyway, Good luck, Richardo! -- 09/25/2016

你可能感兴趣的:(Leetcode - Number of Islands)