LeetCode number of islands (200 questions) DFS, BFS, combined search

Number of LeetCode Islands

@author:Jingdai
@date:2020.12.29

Title description (200 questions)

Given a two-dimensional grid composed of '1'(land) and '0'(water), please count the number of islands in the grid.

Islands are always surrounded by water, and each island can only be formed by connecting adjacent land in the horizontal and/or vertical direction.

In addition, you can assume that all four sides of the grid are surrounded by water.

Example:

输入:grid = [
 ["1","1","0","0","0"],
 ["1","1","0","0","0"],
 ["0","0","1","0","0"],
 ["0","0","0","1","1"]
]
输出:3

Idea and code

Method 1 DFS and BFS

Carefully read the title, you can find that in fact the subject is required grid is '0'divided into a few pieces, there are a few that there are several islands. As shown in the example in '0'the grid '1'is divided into three, the result is three islands.

Insert picture description here

Based on this, we can traverse the entire grid, if met '1', would it be DFS or BFS, it will start communicating '1'all become '2', with '2'expressed land visited. In the process of traversing the grid, each new one encountered '1'indicates a new island, and the number of islands is increased by one. The following is the specific code.

The DFS code is as follows.

public int numIslands(char[][] grid) {
    
    
    int row = grid.length;
    int column = grid[0].length;
    int island = 0;
    for (int i = 0; i < row; i++) {
    
    
        for (int j = 0; j < column; j++) {
    
    
            if (grid[i][j] == '1') {
    
    
                island++;
                dfs(grid, i, j);
            }
        }
    }
    return island;
}

public void dfs(char[][] grid, int i, int j) {
    
    
    grid[i][j] = '2';
    int row = grid.length;
    int column = grid[0].length;
    // right  i    j+1
    // down   i+1  j
    // left   i    j-1
    // up     i-1  j

    if (j+1 < column && grid[i][j+1] == '1') {
    
    
        dfs(grid, i, j+1);
    } 
    if (i+1 < row && grid[i+1][j] == '1') {
    
    
        dfs(grid, i+1, j);
    } 
    if (j-1 >= 0 && grid[i][j-1] == '1') {
    
    
        dfs(grid, i, j-1);
    }
    if (i-1 >= 0 && grid[i-1][j] == '1') {
    
    
        dfs(grid, i-1, j);
    }
}

The BFS code is as follows.

public int numIslands(char[][] grid) {
    
    
    int row = grid.length;
    int column = grid[0].length;
    int island = 0;
    for (int i = 0; i < row; i++) {
    
    
        for (int j = 0; j < column; j++) {
    
    
            if (grid[i][j] == '1') {
    
    
                island++;
                bfs(grid, i, j);
            }
        }
    }
    return island;
}

public void bfs(char[][] grid, int i, int j) {
    
    
    // ** visit when enqueue
    int row = grid.length;
    int column = grid[0].length;
    // right  i    j+1
    // down   i+1  j
    // left   i    j-1
    // up     i-1  j
    LinkedList<int[]> queue = new LinkedList<>();
    queue.offer(new int[]{
    
    i, j});
    grid[i][j] = '2';
    while (queue.size() != 0) {
    
    
        int[] cur = queue.poll();
        if (cur[1]+1 < column && grid[cur[0]][cur[1]+1] == '1') {
    
    
            queue.offer(new int[]{
    
    cur[0], cur[1]+1});
            grid[cur[0]][cur[1]+1] = '2';
        }
        if (cur[0]+1 < row && grid[cur[0]+1][cur[1]] == '1') {
    
    
            queue.offer(new int[]{
    
    cur[0]+1, cur[1]});
            grid[cur[0]+1][cur[1]] = '2';
        }
        if (cur[1]-1 >= 0 && grid[cur[0]][cur[1]-1] == '1') {
    
    
            queue.offer(new int[]{
    
    cur[0], cur[1]-1});
            grid[cur[0]][cur[1]-1] = '2';
        }
        if (cur[0]-1 >= 0 && grid[cur[0]-1][cur[1]] == '1') {
    
    
            queue.offer(new int[]{
    
    cur[0]-1, cur[1]});
            grid[cur[0]-1][cur[1]] = '2';
        }
    }
}

Method 2 and check set

This problem can also be solved by using the union search data structure. Or to traverse the entire grid when one encounters '1'when we put it next point in four directions have a look to see whether '1', and if so '1', we will them unionup. Remember, the number required in the islands, is seeking disconnected collection of a few, we can grid recorded a total '1'number, with a '1'total of minus centralized and check the success of unionthe number is the number of the last set of disconnected.

In fact, you can also optimize it, we had a top '1'time, we will point next to it are the four directions of the look, in fact, not so much. We can actually only look at the right and the bottom, because if there is one on the top, it must have been connected when visiting the above point. The same goes for the left. The final code is as follows.

// Disjoint Set
private class DisjointSet {
    
    

    int[] parent;
    int jointNumber = 0;

    DisjointSet(int number) {
    
    
        parent = new int[number];
        Arrays.fill(parent, -1);
    }

    int find(int n) {
    
    
        int p = n;
        while (parent[p] >= 0) {
    
    
            p = parent[p];
        }
        int cur = n;
        int temp;
        // parent[cur] > 0 for initial is -1
        while (parent[cur] >= 0 && parent[cur] != p) {
    
    
            temp = parent[cur];
            parent[cur] = p;
            cur = temp;
        }
        return p;
    }

    void union(int x, int y) {
    
    
        int xParent = find(x);
        int yParent = find(y);
        if (xParent == yParent)
            return;
        parent[yParent] += parent[xParent]; 
        parent[xParent] = yParent;
        jointNumber++;
    }
}

public int numIslands(char[][] grid) {
    
    

    int row = grid.length;
    int column = grid[0].length;
    int lands = 0;

    DisjointSet disjointSet = new DisjointSet(row * column);

    for (int i = 0; i < row; i++) {
    
    
        for (int j = 0; j < column; j++) {
    
    
            if (grid[i][j] == '1') {
    
    
                lands++;
                // right
                if (j+1 < column && grid[i][j+1] == '1') {
    
    
                    disjointSet.union(i*column+j, i*column+j+1);
                }
                // under
                if (i+1 < row && grid[i+1][j] == '1') {
    
    
                    disjointSet.union(i*column+j, (i+1)*column+j);
                }
            }
        }
    }
    return lands - disjointSet.jointNumber;
}

Guess you like

Origin blog.csdn.net/qq_41512783/article/details/111936771