El tiempo de un rey para lidiar con el problema de la isla (dfs)

1. El número de islas

contenido

1. El número de islas

2. El perímetro de la isla

3. Superficie máxima de la isla

4. Estadísticas sobre el número de islas cerradas

V. Número de enclaves

 6 Cuente el número de sub-islas


Enlace de código de lete correspondiente:

200. Número de islas - LeetCode (leetcode-cn.com)

Tema Descripción:

Ideas para resolver problemas:

Primero aclaramos cómo se define la estructura de cuadrícula en el problema de la isla para facilitar nuestra discusión posterior.

El problema de la cuadrícula es una cuadrícula compuesta por m × n cuadrados pequeños, y cada cuadrado pequeño se considera adyacente a sus cuatro cuadrados, arriba, abajo, izquierda y derecha, y se debe realizar algún tipo de búsqueda en dicha cuadrícula. .

El problema de la isla es un problema de red típico. Los números en cada celda pueden ser 0 o 1. Consideramos la cuadrícula con el número 0 como la cuadrícula oceánica, y la cuadrícula con el número 1 como la cuadrícula terrestre, de modo que las cuadrículas terrestres adyacentes están conectadas para formar una isla.

 Solo necesitamos dos bucles for para atravesar la matriz e iniciar la infección y la recursión en sus cuatro direcciones, si encuentra 1, se cambiará a 0. Si no es 1, regresará directamente si está fuera de los límites.

Código correspondiente:

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);
    }
};

Sin embargo, la matriz original debe repararse de esta manera. El bloguero no se siente bien y se siente demasiado frustrado. El bloguero da otra solución: definir una matriz bidimensional para registrar las ubicaciones visitadas. El código se da a continuación:

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. El perímetro de la isla

463. El perímetro de la isla - LeetCode (leetcode-cn.com)

Tema Descripción:

 

 Ideas para resolver problemas:

La idea de esta pregunta es básicamente la misma que la pregunta anterior, excepto que si esta pregunta llega al límite, debemos devolver 1, porque si cruza el límite, significa que se ha encontrado un borde en el perímetro. De manera similar, necesitamos cambiar todos los 1 encontrados en la recursión a otros números, de lo contrario, la recursión no podrá detenerse.

 Aquí optamos por cambiarlo a 2.:

Código correspondiente:

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);
        }
    }
    
};

De manera similar, si no queremos modificar la matriz, podemos definir una matriz bidimensional para registrar las posiciones visitadas:

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. Superficie máxima de la isla

La espada se refiere a la Oferta II 105. El área más grande de la isla - LeetCode (leetcode-cn.com)

Tema Descripción:

 Ideas para resolver problemas:

La idea de esta pregunta es básicamente la misma que la pregunta anterior. La pregunta anterior es ans+=. Esta pregunta solo necesita compararse con el valor devuelto.

Código correspondiente:

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;
    }
};

Se dan las mismas dos formas: una usa una matriz bidimensional para registrar la posición y la segunda forma es cambiar el valor en la matriz original.

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. Estadísticas sobre el número de islas cerradas

Enlace de código de lete correspondiente:

1254. Contando el número de islas cerradas - LeetCode (leetcode-cn.com)

Tema Descripción:

 No se puede decir que la idea de esta pregunta y la pregunta anterior sean similares, pero son exactamente lo mismo. La idea es recurrir en cuatro direcciones si una posición es 1.

Código correspondiente:

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. Número de enclaves

1020. Número de enclaves - LeetCode (leetcode-cn.com)

Tema Descripción:

Ideas para resolver problemas:

Este problema es equivalente a encontrar la suma de áreas de bloques independientes que no están conectados al borde, solo aplica la plantilla del problema anterior. Por favor vea el código para más detalles

Código correspondiente:

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 Cuente el número de sub-islas

1905. Subislas estadísticas - LeetCode (leetcode-cn.com)

 Tema Descripción:

 Ideas para resolver problemas:

Esta pregunta es un poco más complicada y se agrega una condición de juicio, de hecho, se requiere que todos los lugares que se recorren a 1 en un dfs de grid2 también sean 1 en grid1. Piense en esta pregunta como una pregunta similar para el número de islas .

Código correspondiente:

Lo mismo da dos versiones:

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) ;
    }
};

Método 2: modifique el valor en la matriz original:

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];
    }
};

 

Supongo que te gusta

Origin blog.csdn.net/qq_56999918/article/details/123674375
Recomendado
Clasificación