A king's time to deal with the island problem (dfs)

1. The number of islands

content

1. The number of islands

2. The perimeter of the island

3. Maximum area of ​​the island

4. Statistics on the number of closed islands

V. Number of enclaves

 6 Count the number of sub-islands


Corresponding letecode link:

200. Number of Islands - LeetCode (leetcode-cn.com)

Topic description:

Problem solving ideas:

We first clarify how the grid structure in the island problem is defined to facilitate our later discussion.

The grid problem is a grid composed of m × n small squares, and each small square is considered to be adjacent to its four squares, up, down, left, and right, and some kind of search is to be performed on such a grid.

The island problem is a typical grid problem. The numbers in each cell may be 0 or 1. We regard the grid with the number 0 as the ocean grid, and the grid with the number 1 as the land grid, so that the adjacent land grids are connected to form an island

 We only need two for loops to traverse the array and start the infection and recursion in its four directions. If it encounters 1, it will be changed to 0. If it is not 1, it will return directly if it is out of bounds.

Corresponding code:

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
               int ans=0;
               for(int i=0;i<grid.size();i++){
                   for(int j=0;j<grid[0].size();j++){
                       if(grid[i][j]=='1'){//如果是1就递归去感染
                           ans++;//数量加加
                           infect(grid,i,j);
                       }
                   }
               }
               return ans;
    }
    void infect(vector<vector<char>>&board,int i,int j){
        if(i<0||i==board.size()||j<0||j==board[0].size()||board[i][j]!='1'){
            //越界直接返回或者不是字符一
            return;
        }
        board[i][j]='0';//将其该为0
        //向四个方向感染
        infect(board,i-1,j);
        infect(board,i+1,j);
        infect(board,i,j-1);
        infect(board,i,j+1);
    }
};

However, the original array should be repaired in this way. The blogger does not feel good and feels too frustrated. The blogger gives another solution: define a two-dimensional array to record the visited locations. The code is given below:

class Solution {
public:
       vector<vector<bool>>visit;
    int numIslands(vector<vector<char>>& grid) {
          visit.resize(grid.size(),vector<bool>(grid[0].size()));
               int ans=0;
               for(int i=0;i<grid.size();i++){
                   for(int j=0;j<grid[0].size();j++){
                       if(grid[i][j]=='1'&&!visit[i][j]){//已经访问过了不要再访问了
                    
                           ans++;
                           infect(grid,i,j);
                       }
                   }
               }
               return ans;
    }
    void infect(vector<vector<char>>&board,int i,int j){
        if(i<0||i==board.size()||j<0||j==board[0].size()){//越界直接返回
            return;
        }
        if(board[i][j]=='0'){
            return;//不是字符1也直接返回
        }
        if(visit[i][j]){//已经访问过了直接返回
            return;
        }
        visit[i][j]=true;//记录
        //往四个方向感染
        infect(board,i-1,j);
        infect(board,i+1,j);
        infect(board,i,j-1);
        infect(board,i,j+1);
    }
};

2. The perimeter of the island

463. The Perimeter of the Island - LeetCode (leetcode-cn.com)

Topic description:

 

 Problem solving ideas:

The idea of ​​this question is basically the same as the previous question, except that if this question reaches the boundary, we need to return 1, because if it crosses the boundary, it means that an edge in the perimeter has been found. Similarly, we need to change all 1 encountered in the recursion to other numbers, otherwise the recursion will not be able to stop

 Here we choose to change it to 2.:

Corresponding code:

class Solution {
public:
    int islandPerimeter(vector<vector<int>>& grid) {
          int m=grid.size();
          int ans=0;
          int n=grid[0].size();
          for(int i=0;i<m;i++){
              for(int j=0;j<n;j++){
                  if(grid[i][j]==1){//如果为1直接记录感染记录答案
                      ans+=infect(grid,i,j);
                  }
              }
          }
          return ans;
    }
    int infect(vector<vector<int>>&grid,int row ,int col){
        if(row>=grid.size()||col>=grid[0].size()||row<0||col<0){//越界返回1说明是边界
            return 1;
        }
        else if(grid[row][col]==2){//说明之前已经访问过了
            return 0;
        }
        else if(grid[row][col]==0){//等于0返回
            return 1;
        }
        else{
            grid[row][col]=2;//说明是1将其改成2即可下次进来就不会重复计算
         return   infect(grid,row+1,col)+//四个方向的结果累加
            infect(grid,row-1,col)+
            infect(grid,row,col-1)+
            infect(grid,row,col+1);
        }
    }
    
};

Similarly, if we don't want to modify the array, we can define a two-dimensional array to record the visited positions:

class Solution {
public:
      vector<vector<bool>>visit;//记录二维表中某个位置是否被访问
    int islandPerimeter(vector<vector<int>>& grid) {
          int m=grid.size();
          int ans=0;
          int n=grid[0].size();
          visit.resize(m,vector<bool>(n));
          for(int i=0;i<m;i++){
              for(int j=0;j<n;j++){

                  if(grid[i][j]==1&&!visit[i][j]){//如果已经被访问过了直接跳过
                      ans+=infect(grid,i,j);
                  }

              }
          }
          return ans;
    }
    int infect(vector<vector<int>>&grid,int row ,int col){
        if(row>=grid.size()||col>=grid[0].size()||row<0||col<0){//越界返回1说明是边界
            return 1;
        }
        else if(visit[row][col]){//说明之前已经访问过了
            return 0;
        }
        else if(grid[row][col]==0){//等于0返回
            return 1;
        }
        else{
           visit[row][col]=true;
         return   infect(grid,row+1,col)+//四个方向的结果累加
            infect(grid,row-1,col)+
            infect(grid,row,col-1)+
            infect(grid,row,col+1);
        }
    }
    
};

3. Maximum area of ​​the island

The sword refers to Offer II 105. The largest area of ​​the island - LeetCode (leetcode-cn.com)

Topic description:

 Problem solving ideas:

The idea of ​​this question is basically the same as the previous question. The above question is ans+=. This question only needs to be compared with the return value.

Corresponding code:

class Solution {
public:
vector<vector<bool>>visit;
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int ans=0;
        visit.resize(grid.size(),vector<bool>(grid[0].size()));
            for(int i=0;i<grid.size();i++){
                for(int j=0;j<grid[0].size();j++){
                    if(grid[i][j]==1){//如果等于1就感染更新答案
                      ans=max(dfs(grid,i,j),ans);
                    }
                }
            }
            return ans;
    }
    int dfs(vector<vector<int>>&grid,int row,int col){
             if(row<0||col<0||row>=grid.size()||col>=grid[0].size()||visit[row][col]){
                 return 0;//visit[row][col]=true说明已经访问过了
             }
             else if(grid[row][col]==1){
                visit[row][col]=true;
                 return 1+dfs(grid,row,col-1)+dfs(grid,row,col+1)//自己加上四个方向的数量
                 +dfs(grid,row+1,col)+dfs(grid,row-1,col);
             }
             //说明它等于grid[row][col]=0直接返回0即可
             return 0;
    }
};

The same two ways are given. One uses a two-dimensional array to record the position, and the second way is to change the value in the original array.

class Solution {
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int ans=0;
            for(int i=0;i<grid.size();i++){
                for(int j=0;j<grid[0].size();j++){
                    if(grid[i][j]==1){//等于1向四个方向感染并更新答案
                      ans=max(dfs(grid,i,j),ans);
                    }
                }
            }
            return ans;
    }
    int dfs(vector<vector<int>>&grid,int row,int col){
             if(row<0||col<0||row>=grid.size()||col>=grid[0].size()){
                 return 0;
             }
             else if(grid[row][col]==1){
                 grid[row][col]=0;//访问过将其改为0;
                 return 1+dfs(grid,row,col-1)+dfs(grid,row,col+1)//四个方向递归
                 +dfs(grid,row+1,col)+dfs(grid,row-1,col);
             }
             //说明它等于grid[row][col]=0
             return 0;
    }
};

4. Statistics on the number of closed islands

Corresponding letecode link:

1254. Counting the Number of Closed Islands - LeetCode (leetcode-cn.com)

Topic description:

 The idea of ​​this question and the above question cannot be said to be similar, but they are exactly the same. The idea is to recurse in four directions if a position is 1.

Corresponding code:

class Solution {
public:
          vector<vector<bool>>visit;//记录每个位置是否记录过
    int closedIsland(vector<vector<int>>& grid) {
             visit.resize(grid.size(),vector<bool>(grid[0].size()));
             int ans=0;
             for(int i=0;i<grid.size();i++){
                 for(int j=0;j<grid[0].size();j++){
                     if(grid[i][j]==0&&!visit[i][j]){
                         if(!dfs(grid,i,j)){//如果返回的结果为false说明找到了
                             ans++;
                         }
                     }
                 }
             }
             return ans;
    }
    bool dfs(vector<vector<int>>&grid,int row,int col){
        if(row<0||row>=grid.size()||col<0||col>=grid[0].size()){
            return true;
        }
            if(grid[row][col]==1){
                return false;
            }
            if(visit[row][col]){//判断是否已经访问过了
                return false;
            }
            visit[row][col]=true;
            //四个方向都要遍历不能只遍历一个方向
            bool ret1= dfs(grid,row,col-1);//四个方向一点要遍历完毕才能停止
            bool ret2=dfs(grid,row,col+1);
            bool ret3=dfs(grid,row+1,col);
            bool ret4=dfs(grid,row-1,col);
    
          return ret1||ret2||ret3||ret4;//四个方向只要一个为true就直接返回
        
    }
};

V. Number of enclaves

1020. Number of Enclaves - LeetCode (leetcode-cn.com)

Topic description:

Problem solving ideas:

This problem is equivalent to finding the area sum of independent blocks that are not connected to the edge, just apply the template of the above problem. Please see the code for details

Corresponding code:

class Solution {
public:
vector<vector<bool>>visit;

    int numEnclaves(vector<vector<int>>& grid) {
         visit.resize(grid.size(),vector<bool>(grid[0].size()));
       int m=grid.size();
       int n=grid[0].size();
    visit.resize(m,vector<bool>(n));//记录每个位置是否被访问过
         int ret=0;
         for(int i=0;i<m;i++){
             for(int j=0;j<n;j++){
                 //从边界开始感染
                 if(!i||!j||i==m-1||j==n-1&&grid[i][j]&&!visit[i][j]){//如果是边界向四方感
                     dfs(grid,i,j);
                 }
             }
         }
         
         for(int i=0;i<grid.size();i++){
             for(int j=0;j<grid[0].size();j++){
                 if(grid[i][j]==1&&!visit[i][j]){//如果它是1并且没有被感染过
                     ret++;
                 }
             }
         }
         return ret;
    }
    void dfs(vector<vector<int>>&grid,int row,int col){
       
        if(row>=0&&row<grid.size()&&col<grid[0].size()&&col>=0&&!visit[row][col]&&grid[row][col]!=0){
              visit[row][col]=true;
             dfs(grid,row,col-1);
             dfs(grid,row,col+1);
             dfs(grid,row+1,col);
             dfs(grid,row-1,col);
        }
       
       
    }
};

 6 Count the number of sub-islands

1905. Statistical Sub-Islands - LeetCode (leetcode-cn.com)

 Topic description:

 Problem solving ideas:

This question is a little more complicated, and a judgment condition is added. In fact, it is required that all the places that are traversed to 1 in a dfs of grid2 are also 1 in grid1. Think of this question as a similar question for the number of islands .

Corresponding code:

The same gives two versions:

class Solution {
public:
          vector<vector<bool>>visit;
    int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2) {
        int m = grid2.size(), n = grid2[0].size(), res = 0;
              visit.resize(m,vector<bool>(n));
        for (int row = 0; row < m; row++)
            for (int col = 0; col < n; col++)
                if (grid2[row][col]&&!visit[row][col])//该点为1并且已经访问过了
                    res += dfs(grid1, grid2, row, col);
        return res;
    }

private:
    bool dfs(vector<vector<int>>& grid1, vector<vector<int>>& grid2, int row, int col) {
        if(row < 0 || col < 0 || row >= grid2.size() || col >= grid2[0].size() || 
            !grid2[row][col]) return true;
            if(visit[row][col])//访问过了之后直接返回
            {
                return true;
            }
          visit[row][col]=true;//将其标记为true说明已经访问过了

        return 
            grid1[row][col]&dfs(grid1, grid2, row + 1, col) & dfs(grid1, grid2, row - 1, col) &dfs(grid1, grid2, row, col + 1) & dfs(grid1, grid2, row , col - 1) ;
    }
};

Method 2: Modify the value in the original array:

class Solution {
public:
    int countSubIslands(vector<vector<int>>& grid1, vector<vector<int>>& grid2) {
        int m = grid2.size(), n = grid2[0].size(), res = 0;
        for (int row = 0; row < m; row++)
            for (int col = 0; col < n; col++)
                if (grid2[row][col])//如果是1
                    res += dfs(grid1, grid2, row, col);
        return res;
    }

private:
    bool dfs(vector<vector<int>>& grid1, vector<vector<int>>& grid2, int row, int col) {
        if(row < 0 || col < 0 || row >= grid2.size() || col >= grid2[0].size() || 
            !grid2[row][col]) return true;
        grid2[row][col] = 0; // 设置已经遍历过标志
        //四个方向都遍历
        return dfs(grid1, grid2, row + 1, col) & dfs(grid1, grid2, row - 1, col) &
            dfs(grid1, grid2, row, col + 1) & dfs(grid1, grid2, row , col - 1) & 
            grid1[row][col];
    }
};

 

Guess you like

Origin blog.csdn.net/qq_56999918/article/details/123674375