Given a 2d grid map of
'1'
s (land) and '0'
s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
11110 11010 11000 00000
Answer: 1
Example 2:
11000 11000 00100 00011
Answer: 3
Analysis:
One simple solution for this problem is to use BFS or DFS. Simply scan the grid line by line, when you find a '1', DFS/BFS from it to search neighboring '1', until all the '1' cells connecting to it have been visited. Then you find one region. We call this procedure as "region growing", a popular algorithm in computer graphics. You should mark all visited '1' cells as visited. Then scan the grid again and find another unvisited '1' and do the above procedure again. When you scan the whole grid, you will get all islands.
Here I propose another solution. We give a ID for each island, beginning from count = 2 (use 'count' to represent the ID. 0 and 1 are used for water and land). First, we scan the grid line by line and when you find a cell with '1', you check its four neighbors. If its all neighbors are either '0' or '1', which means all its neighbors are not visited or water. Then you find a new island! Mark this island using count and increase the count by 1. Else, if you find some neighbors are not '0' or '1', this indicates the current cell is connected with some other islands. Pick the island which has the smallest ID and then mark the current cell using this ID and also remark all connected islands using this ID. In this way, you will merge all disjointed islands which are connected by the current cell. Keep doing this until you finish scanning the whole grid.
Here I propose another solution. We give a ID for each island, beginning from count = 2 (use 'count' to represent the ID. 0 and 1 are used for water and land). First, we scan the grid line by line and when you find a cell with '1', you check its four neighbors. If its all neighbors are either '0' or '1', which means all its neighbors are not visited or water. Then you find a new island! Mark this island using count and increase the count by 1. Else, if you find some neighbors are not '0' or '1', this indicates the current cell is connected with some other islands. Pick the island which has the smallest ID and then mark the current cell using this ID and also remark all connected islands using this ID. In this way, you will merge all disjointed islands which are connected by the current cell. Keep doing this until you finish scanning the whole grid.
C++:
class Solution {
public:
struct point{
int X;
int Y;
char key;
};
struct island{
vector<point> points;
char key;
};
map<char, island> islands;
void updateIsland(island isd, char key, vector<vector<char>> &grid){
for(int i = 0; i<isd.points.size(); i++){
isd.points[i].key = key;
grid[isd.points[i].Y][isd.points[i].X] = key;
islands[key].points.push_back(isd.points[i]);
}
islands.erase(isd.key);
}
int numIslands(vector<vector<char>> &grid) {
int h = grid.size();
if(h==0)
return 0;
int w = grid[0].size();
for(int i=0; i<h; ++i){
for(int j=0; j<w; ++j){
if(grid[i][j]=='1'){
grid[i][j] = 0;
}
else{
grid[i][j] = 1;
}
}
}
char count=2;
for(int i=0; i<h; ++i){
for(int j=0; j<w; ++j){
if(grid[i][j]==0){
vector<char> neib;
int left = j-1; int right = j+1; int top = i-1; int bottom = i+1;
if(left>=0 && grid[i][left]!=0 && grid[i][left]!=1){
neib.push_back(grid[i][left]);
}
if(right<=w-1 && grid[i][right]!=0 && grid[i][right]!=1){
neib.push_back(grid[i][right]);
}
if(top>=0 && grid[top][j]!=0 && grid[top][j]!=1){
neib.push_back(grid[top][j]);
}
if(bottom<=h-1 && grid[bottom][j]!=0 && grid[bottom][j]!=1){
neib.push_back(grid[bottom][j]);
}
if(neib.size()!=0){
char min=127;
for(int a=0; a<neib.size(); a++){
if(neib[a]<min)
min = neib[a];
}
for(int a=0; a<neib.size(); a++){
if(neib[a]!=min){
updateIsland(islands[neib[a]], min, grid);
}
}
grid[i][j] = min;
point p = {j, i, min};
islands[min].points.push_back(p);
}
else{
grid[i][j] = count;
point p = {j, i, count};
vector<point> pv;
island isld = {pv, count};
isld.points.push_back(p);
islands[count] = isld;
count++;
}
}
}
}
return islands.size();
}
};
public:
struct point{
int X;
int Y;
char key;
};
struct island{
vector<point> points;
char key;
};
map<char, island> islands;
void updateIsland(island isd, char key, vector<vector<char>> &grid){
for(int i = 0; i<isd.points.size(); i++){
isd.points[i].key = key;
grid[isd.points[i].Y][isd.points[i].X] = key;
islands[key].points.push_back(isd.points[i]);
}
islands.erase(isd.key);
}
int numIslands(vector<vector<char>> &grid) {
int h = grid.size();
if(h==0)
return 0;
int w = grid[0].size();
for(int i=0; i<h; ++i){
for(int j=0; j<w; ++j){
if(grid[i][j]=='1'){
grid[i][j] = 0;
}
else{
grid[i][j] = 1;
}
}
}
char count=2;
for(int i=0; i<h; ++i){
for(int j=0; j<w; ++j){
if(grid[i][j]==0){
vector<char> neib;
int left = j-1; int right = j+1; int top = i-1; int bottom = i+1;
if(left>=0 && grid[i][left]!=0 && grid[i][left]!=1){
neib.push_back(grid[i][left]);
}
if(right<=w-1 && grid[i][right]!=0 && grid[i][right]!=1){
neib.push_back(grid[i][right]);
}
if(top>=0 && grid[top][j]!=0 && grid[top][j]!=1){
neib.push_back(grid[top][j]);
}
if(bottom<=h-1 && grid[bottom][j]!=0 && grid[bottom][j]!=1){
neib.push_back(grid[bottom][j]);
}
if(neib.size()!=0){
char min=127;
for(int a=0; a<neib.size(); a++){
if(neib[a]<min)
min = neib[a];
}
for(int a=0; a<neib.size(); a++){
if(neib[a]!=min){
updateIsland(islands[neib[a]], min, grid);
}
}
grid[i][j] = min;
point p = {j, i, min};
islands[min].points.push_back(p);
}
else{
grid[i][j] = count;
point p = {j, i, count};
vector<point> pv;
island isld = {pv, count};
isld.points.push_back(p);
islands[count] = isld;
count++;
}
}
}
}
return islands.size();
}
};