C++ DFS与并查集两种解法

岛屿数量

http://www.nowcoder.com/questionTerminal/0c9664d1554e466aa107d899418e814e

这是一个关于图(graph)的问题。矩阵每个点对于图的一个节点,每个图节点有前后左右四个不同方向。问题的目标是找到有几个全为1的连通域。那么两种解法,并查集和DFS。
DFS思路:

void dfsIslands(vector<vector<char>>& grid, unordered_map<int, bool>& visited, int size, int cur) {
    visited[cur] = true;
    int m = (int)grid.size(), n = (int)grid[0].size();
    int i = cur / size, j = cur % size;
    vector<vector<int>> direction = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};
    for (auto dir:direction) {
        int nexti = i + dir[0], nextj = j + dir[1];
        if (nexti >= m || nexti < 0 || nextj >= n || nextj < 0 || visited[nexti * size + nextj]) continue;
        if (grid[nexti][nextj] == '0') {
            visited[nexti * size + nextj] = true;
            continue;
        }
        dfsIslands(grid, visited, size, nexti * size + nextj);
    }
}
int solve(vector<vector<char>>& grid) {
    // write code here
    int m = (int)grid.size(), n = (int)grid[0].size(), size = max(m, n), res = 0;
    unordered_map<int, bool> visited;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (grid[i][j] == '0' || visited[i * size + j]) {
                visited[i * size + j] = true;
                continue;
            }
            res++;
            dfsIslands(grid, visited, size, i * size + j);
        }
    }
    return res;
}

下面是并查集(union_find)的解法。并查集是一个高级数据结构,其定义每个节点有一个father,若一个集合里是连通的,那么该集合就会有共同的father。并查集有两个主要的函数,其一是找father点的函数,其二是合并的操作。代码细节如下:

class unionFind_islands {
private:
    vector<int> father, rank;
public:
    int count = 0;
    int m, n;

    unionFind_islands(vector<vector<char>>& grid) {
        m = (int)grid.size();
        n = (int)grid[0].size();
        father = vector<int> (m * n);
        rank = vector<int> (m * n);
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                father[i * n + j] = i * n + j;
                rank[i * n + j] = 1;
                if (grid[i][j] == '1') count++;
            }
        }
    }

    int findFather(int cur) {
        if (father[cur] == cur) return cur;
        return father[cur] = findFather(father[cur]);
    }

    void unionIslands(int i, int j) {
        int faA = findFather(i);
        int faB = findFather(j);
        if (faA == faB) return;
        count--;
        if (rank[faA] > rank[faB]) father[faB] = faA;
        else if (rank[faB] == rank[faA]) {
            father[faB] = faA;
            rank[faA]++;
        }
        else father[faA] = faB;
    }

};
int solve(vector<vector<char>>& grid) {
    unionFind_islands uf = unionFind_islands(grid);
    vector<vector<int>> direction = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};
    for (int i = 0; i < uf.m; i++) {
        for (int j = 0; j < uf.n; j++) {
            if (grid[i][j] == '1') {
                for (auto dir:direction) {
                    int nexti = i + dir[0], nextj = j + dir[1];
                    if (nexti < 0 || nexti >= uf.m || nextj < 0 || nextj >= uf.n) continue;
                    if (grid[nexti][nextj] == '1') uf.unionIslands(i * uf.n + j, nexti * uf.n + nextj);
                }
            }
        }
    }
    return uf.count;
}
全部评论

相关推荐

评论
1
收藏
分享
牛客网
牛客企业服务