leetcode刷题日记——岛屿数量
[ 题目描述 ]:
[ 思路 ]:
- 一个独立的岛屿其周围都是0,那么从某一个 1 出发,将其上下左右包含其自身的 1 全部设置为0,就相当于去除了一片大陆,大陆数+1,然后寻找下一个 1 去进行重复操作,直到整个图都是 0
- 那么从第 [0,0] 个元素开始,如果其是 1 ,那么去判断,他右边 [0,1] 和下边 [1,0] 元素是否为1
- 为 1,则需要去探寻该元素的上下左右元素是否为 1 (递归)
- 为 0,说明抵达了这偏大陆的边界,设置其自身为0,结束这个方向的探寻
- 每消除一片大陆,大陆数+1
- 运行如下
void eliminate(char** grid,int row,int column,int gridSize, int* gridColSize){grid[row][column]='0';if(row-1>=0 && grid[row-1][column]=='1') eliminate(grid,row-1,column,gridSize,gridColSize);if(row+1<gridSize && grid[row+1][column]=='1') eliminate(grid,row+1,column,gridSize,gridColSize);if(column-1>=0 && grid[row][column-1]=='1') eliminate(grid,row,column-1,gridSize,gridColSize);if(column+1<gridColSize[row] && grid[row][column+1]=='1') eliminate(grid,row,column+1,gridSize,gridColSize);
}int numIslands(char** grid, int gridSize, int* gridColSize) {int landsum=0;for(int i=0;i<gridSize;i++){for(int j=0;j<gridColSize[i];j++){if(grid[i][j]=='1'){eliminate(grid,i,j,gridSize,gridColSize);landsum++;}}}return landsum;
}
[ 官方题解 ]:
- 方法一:深度优先搜索,基本同上
- 方法二:广度优先搜索,扫描整个二维网格。如果一个位置为 1,则将其加入队列,开始进行广度优先搜索。在广度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0。直到队列为空,搜索结束。最终岛屿的数量就是我们进行广度优先搜索的次数。
class Solution {
public:int numIslands(vector<vector<char>>& grid) {int nr = grid.size();if (!nr) return 0;int nc = grid[0].size();int num_islands = 0;for (int r = 0; r < nr; ++r) {for (int c = 0; c < nc; ++c) {if (grid[r][c] == '1') {++num_islands;grid[r][c] = '0';queue<pair<int, int>> neighbors;neighbors.push({r, c});while (!neighbors.empty()) {auto rc = neighbors.front();neighbors.pop();int row = rc.first, col = rc.second;if (row - 1 >= 0 && grid[row-1][col] == '1') {neighbors.push({row-1, col});grid[row-1][col] = '0';}if (row + 1 < nr && grid[row+1][col] == '1') {neighbors.push({row+1, col});grid[row+1][col] = '0';}if (col - 1 >= 0 && grid[row][col-1] == '1') {neighbors.push({row, col-1});grid[row][col-1] = '0';}if (col + 1 < nc && grid[row][col+1] == '1') {neighbors.push({row, col+1});grid[row][col+1] = '0';}}}}}return num_islands;}
};
- 方法三:并查集,如果一个位置为 1,则将其与相邻四个方向上的 1 在并查集中进行合并。最终岛屿的数量就是并查集中连通分量的数目。
class UnionFind {
public:UnionFind(vector<vector<char>>& grid) {count = 0;int m = grid.size();int n = grid[0].size();for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {if (grid[i][j] == '1') {parent.push_back(i * n + j);++count;}else {parent.push_back(-1);}rank.push_back(0);}}}int find(int i) {if (parent[i] != i) {parent[i] = find(parent[i]);}return parent[i];}void unite(int x, int y) {int rootx = find(x);int rooty = find(y);if (rootx != rooty) {if (rank[rootx] < rank[rooty]) {swap(rootx, rooty);}parent[rooty] = rootx;if (rank[rootx] == rank[rooty]) rank[rootx] += 1;--count;}}int getCount() const {return count;}private:vector<int> parent;vector<int> rank;int count;
};class Solution {
public:int numIslands(vector<vector<char>>& grid) {int nr = grid.size();if (!nr) return 0;int nc = grid[0].size();UnionFind uf(grid);int num_islands = 0;for (int r = 0; r < nr; ++r) {for (int c = 0; c < nc; ++c) {if (grid[r][c] == '1') {grid[r][c] = '0';if (r - 1 >= 0 && grid[r-1][c] == '1') uf.unite(r * nc + c, (r-1) * nc + c);if (r + 1 < nr && grid[r+1][c] == '1') uf.unite(r * nc + c, (r+1) * nc + c);if (c - 1 >= 0 && grid[r][c-1] == '1') uf.unite(r * nc + c, r * nc + c - 1);if (c + 1 < nc && grid[r][c+1] == '1') uf.unite(r * nc + c, r * nc + c + 1);}}}return uf.getCount();}
};