leetcode Questions: Number of Islands

Number of Islands

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:


This is a typical recursive problem which can be solved by either Depth First Search(DFS) or Breath First Search (BFS).

Briefly speaking, DFS is to search every possible directions(solutions) whenever meet the new one, BFS is to search and store every possible directions(solutions) using a queue usually, then search from the head of the queue each time.

In this problem, possible directions are left, right, top, bottom, with constrains that the new location is '1' and has not been visited before. Therefore, we can define a bool matrix (of same size) to store the status of each element in the grid, set it to false when it is not available(been visited).

Details can be found in the code below, which is pretty straightforward.


Code(C++, DFS):

class Solution {
public:

    void search(int i, int j, vector<vector<char>>& grid, vector<vector<bool>>& mark){
        mark[i][j] = false;
        
        if (i+1<grid.size() && grid[i+1][j]=='1' && mark[i+1][j]==true){
            search(i+1,j,grid,mark);
        }
        if (j+1<grid[0].size() && grid[i][j+1]=='1' && mark[i][j+1]==true){
            search(i,j+1,grid,mark);
        }
        if (i-1>=0 && grid[i-1][j]=='1' && mark[i-1][j]==true){
            search(i-1,j,grid,mark);
        }
        if (j-1>=0 && grid[i][j-1]=='1' && mark[i][j-1]==true){
            search(i,j-1,grid,mark);
        }
    }    

    int numIslands(vector<vector<char>>& grid) {
        int row = grid.size();
        if (row==0) return 0;
        int col = grid[0].size();
        
        int res=0;
        
        vector<vector<bool> > mark(row, vector<bool>(col,true));
        
        for (int i=0;i<row;i++){
            for (int j=0;j<col;j++){
                if (grid[i][j] == '1' && mark[i][j] == true){
                    search(i,j,grid,mark);
                    res+=1;
                }
            }
        }
        return res;
        
    }
};

Code(C++, BFS):

class Solution {
public:

    int numIslands(vector<vector<char>>& grid) {
        int row = grid.size();
        if (row==0) return 0;
        int col = grid[0].size();
        
        int res=0;
        
        vector<vector<bool> > mark(row, vector<bool>(col,true));
        
        queue<int> q_row;
        queue<int> q_col;
        
        for (int i=0; i<row; i++){
            for (int j=0; j<col; j++){
                if (grid[i][j]=='1' && mark[i][j]){
                    q_row.push(i);
                    q_col.push(j);
                    mark[i][j] = false;
                    while (!q_row.empty()){
                        int ii = q_row.front();
                        int jj = q_col.front();
                        
                        if (ii+1<row && grid[ii+1][jj]=='1' && mark[ii+1][jj]){
                            q_row.push(ii+1);
                            q_col.push(jj);
                            mark[ii+1][jj] = false;
                        }
                        if (jj+1<col && grid[ii][jj+1]=='1' && mark[ii][jj+1]){
                            q_row.push(ii);
                            q_col.push(jj+1);
                            mark[ii][jj+1] = false;
                        }
                        if (ii-1 >=0 && grid[ii-1][jj]=='1' && mark[ii-1][jj]){
                            q_row.push(ii-1);
                            q_col.push(jj);
                            mark[ii-1][jj] = false;
                        }
                        if (jj-1>=0 && grid[ii][jj-1]=='1' && mark[ii][jj-1]){
                            q_row.push(ii);
                            q_col.push(jj-1);
                            mark[ii][jj-1] = false;
                        }
                        
                        q_row.pop();
                        q_col.pop();
                    }
                    res += 1;
                }
            }
        }
        return res;
    }
};

Code(Python, DFS):

class Solution:
    
    def search(self, i, j, grid, mark):
        mark[i][j] = False
        
        if i+1 < len(grid) and grid[i+1][j] == '1' and mark[i+1][j] == True:
            self.search(i+1,j,grid,mark)
            
        if j+1 < len(grid[0]) and grid[i][j+1] == '1' and mark[i][j+1] == True:
            self.search(i,j+1,grid,mark)
            
        if i-1 >= 0 and grid[i-1][j] == '1' and mark[i-1][j] == True:
            self.search(i-1,j,grid,mark)
            
        if j-1 >=0 and grid[i][j-1] == '1' and mark[i][j-1] == True:
            self.search(i,j-1,grid,mark)
    
    # @param {character[][]} grid
    # @return {integer}
    def numIslands(self, grid):
        row = len(grid)
        if row == 0:
            return 0
        col = len(grid[0])
        
        #mark = [x[:] for x in [[True]*col]*row]
        mark = [[True for x in range(col)] for x in range(row)]
        
        res  = 0
        for i in range(0,row):
            for j in range(0, col):
                if grid[i][j] == '1' and mark[i][j] == True:
                    self.search(i, j, grid,mark)
                    res += 1
        return res
        

Code(Python, BFS):

class Solution:
    # @param {character[][]} grid
    # @return {integer}
    def numIslands(self, grid):
        row = len(grid)
        if row == 0:
            return 0
        col = len(grid[0])
        
        #mark = [x[:] for x in [[True]*col]*row]
        mark = [[True for x in range(col)] for x in range(row)]
        
        res  = 0
        
        q = []
        
        for i in range(0,row):
            for j in range(0, col):
                if grid[i][j] == '1' and mark[i][j] == True:
                    q.append([i,j])
                    mark[i][j] = False
                    while q:
                        ii = q[0][0]
                        jj = q[0][1]
                        q.pop(0)
                        
                        if ii+1 < len(grid) and grid[ii+1][jj] == '1' and mark[ii+1][jj] == True:
                            q.append([ii+1, jj])
                            mark[ii+1][jj] = False
                
                        if jj+1 < len(grid[0]) and grid[ii][jj+1] == '1' and mark[ii][jj+1] == True:
                            q.append([ii, jj+1])
                            mark[ii][jj+1] = False
                
                        if ii-1 >= 0 and grid[ii-1][jj] == '1' and mark[ii-1][jj] == True:
                            q.append([ii-1, jj])
                            mark[ii-1][jj] = False
                
                        if jj-1 >=0 and grid[ii][jj-1] == '1' and mark[ii][jj-1] == True:
                            q.append([ii, jj-1])
                            mark[ii][jj-1] = False
                    res += 1        
                        
        return res
        






2 comments:

  1. Python implementation returns 0 for the test case

    ReplyDelete
  2. Hi Guys

    This is a classic example of BFS implementation. Only catch here is that we don't need extra space to mark a node as visited. Existing grid matrix can be reused to identify a visited node. I have made a small video explaining this logic. Please check this out

    https://www.youtube.com/watch?v=GkG4cQzyFoU

    ReplyDelete