leetcode 200. 岛屿数量

200. 岛屿数量
难度:中
题目概述:找到属于同一个区域的点,典型的并查集问题。。
题解1:DFS
这道题不能采用修改原数组的值做访问标记,所以需要增加一个遍历标记数组。
有些题目,原数组的值会在遍历过程中被修改,所以通常可以直接用原数组的值做标记,进而节省内存。

class Solution {
public:
    int numIslands(vector>& grid) {
        if (grid.empty() || grid[0].empty()) return 0;
        vector> visited(m, vector(n));
        for (int i = 0; i < grid.size(); ++i) {
            for (int j = 0; j < grid[0].size(); ++j) {
                if (grid[i][j] == '0' || visited[i][j]) continue;
                dfs(grid, visited, i, j);
                ++res;
            }
        }
        return res;
    }
    void dfs(vector>& grid, vector>& visited, int x, int y) {
        if (x < 0 || x >= grid.size() || y < 0 || y >= grid[0].size() || grid[x][y] == '0' || visited[x][y]) return;
        visited[x][y] = true;
        dfs(grid, visited, x - 1, y);
        dfs(grid, visited, x + 1, y);
        dfs(grid, visited, x, y - 1);
        dfs(grid, visited, x, y + 1);
    }
};

就dfs而言依然是一道模板题。
题解2:BFS
对于坐标的处理,可以不采用pair的方式,因为pair标记坐标的处理开销要大于int。
通常可以将二维数组转化为一维数组进行处理,用行*列+列的方式标记。

class Solution {
public:
    int numIslands(vector>& grid) {
        if (grid.empty() || grid[0].empty()) return 0;
        int m = grid.size(), n = grid[0].size(), res = 0;
        vector> visited(m, vector(n));
        vector dirx{-1, 0, 1, 0}, diry{0, 1, 0, -1};
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] == '0' || visited[i][j]) continue;
                ++res;
                queue q{{i * n + j}};
                while (!q.empty()) {
                    int t = q.front(); q.pop();
                    for (int k = 0; k < 4; ++k) {
                        int x = t / n + dirx[k], y = t % n + diry[k];
                        if (x < 0 || x >= m || y < 0 || y >= n || grid[x][y] == '0' || visited[x][y] == 1) continue;
                        visited[x][y] = 1;
                        q.push(x * n + y);
                    }
                }
            }
        }
        return res;
    }
};

题解3:并查集
并查集三步法
1.建立根,初始化,每个节点为独立孤岛;建立find和uion函数。上述都是模板
2.根据表的结构关系,建立集合关系。(可能在完成这一步后,题目已经求解)
3.根据题目的具体要求,处理集合关系。

class Solution {
public:
    vector root_group;
    int count=0;
    int numIslands(vector>& grid) {
        if (grid.size() == 0 || grid[0].size() == 0) return 0;
        int length = grid.size() * grid[0].size();
        int width = grid[0].size();
        root_group = vector(length, 0);
        for(int i = 0; i < length; i++) {
            int x = i / width, y = i % width;
            if (grid[x][y] == '1') count++;
            root_group[i] = i;
        }
        for(int j = 0; j < length; j++){
            int x = j / width, y = j % width;
            int down = x + 1, right = y + 1;
            if (down < grid.size() && grid[x][y] == '1' && grid[down][y] == '1')
             unin(j, j+width);
            if ( right < grid[0].size() && grid[x][y] == '1' && grid[x][right] == '1')
             unin(j, j+1);
        }
        return count;
    }

    void unin(int x,int y){
        int rootx = find(x);
        int rooty = find(y);
        if (rootx == rooty)return;
        root_group[rootx] = rooty;
        count--;
    }

    int find(int p){
        while (p != root_group[p]) {
            root_group[p] = root_group[root_group[p]];
            p = root_group[p];
        }
        return p;
    }
};

你可能感兴趣的:(leetcode 200. 岛屿数量)