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;
}
查看8道真题和解析