Explanation of application examples of breadth first search traversal (BFS) on two-dimensional arrays

Posted by AffApprentice on Tue, 21 Sep 2021 01:26:55 +0200

Breadth first search traversal, also known as BFS, belongs to blind search method. It is one of the search algorithms of graph. The purpose is to systematically expand and check all nodes in the graph to find results. In other words, it does not consider the possible location of the result and searches the whole graph thoroughly until it finds the result. Here are some classic examples to lead you to solve together.

(1) Given a matrix mat consisting of 0 and 1  , Please output a matrix of the same size, where each grid is the distance from the corresponding position element in mat to the nearest 0. The distance between two adjacent elements is 1.

  This problem means to solve the distance from each number in the array to the number 0. The distance of 0 itself is 0, and the distance only considers the upper, lower, left, upper right, lower right and other directions. Since the topic calculates the distance from each point to 0, we can put the point 0 into the queue, and then spread from the point 0 to the top, bottom, left and right directions, and mark whether it has been accessed. We can directly modify the value of the original array to mark. Each point enters the queue once. The code is pasted below, and the comments are also as follows:

class Solution {
public:
    vector < vector < int > >updateMatrix(vector< vector< int > > & mat) {
        //Define the coordinates in the up, down, left and right directions to facilitate the mobile access of nodes
        int dirs[4][2] = { {0,1}, {0,-1}, {1,0}, {-1,0}};
        //Number of rows and columns of the array
        int m = mat.size(), n = mat[0].size();
        //Define the result array, and set the initial value of each element to 0
        vector < vector < int > >res(m,vector<int>(n));
        //queue
        queue< pair< int,int > > q;
        //Traverses each element in the array
        for(int i = 0;i < m;i++)
        {
            for(int j = 0;j < n;j++)
            {
                //Add the with array element 0 to the queue
                if(mat[i][j] == 0)
                {
                    q.push( {i,j} );
                }
            }
        }
        //When the queue is not empty
        while(!q.empty())
        {
            //Take out the coordinate values of the team head node respectively
            int x = q.front().first,y = q.front().second;
            //Team leader out of the team
            q.pop();
            //Look for the up, down, left and right directions of the newly extracted head node to see if there is a node with a value of 1
            for(int i = 0;i < 4;i++)
            {
                int nx = x + dirs[i][0],ny = y + dirs[i][1];
                //If the coordinate value is reasonable and the value found is 1 and the result array has not been accessed
              if(nx >= 0 && nx < m && ny>= 0 && ny <n && mat[nx][ny] ==1&&res[nx][ny]==0)
                {
                    //The coordinate value of the new node is the coordinate value of the old node + 1, which means that the distance is one grid farther
                    res[nx][ny] = res[x][y] + 1;
                    //Join the new node in the queue and continue to traverse the search
                    q.push( {nx,ny} );
                }
            }
        }
        return res;
    }
};

(2) There are n cities, some of which are connected to each other, others are not connected. If city a is directly connected to city b and city b is directly connected to City c, city a is indirectly connected to city c. A province is a group of directly or indirectly connected cities, excluding other cities that are not connected. Give you an n x n matrix isConnected, where isConnected[i][j] = 1 means that the ith city and the jth city are directly connected, and isConnected[i][j] = 0 means that they are not directly connected. Returns the number of provinces in the matrix.

To find the number of connected domains in an undirected graph, we can perform a breadth first search on the graph to traverse each node in the graph. Traverse each city in turn. If the city is not visited, start searching near the city until all adjacent cities are visited, that is, get a connected component, that is, a province.   The code is posted below:

class Solution {
public:
    int findCircleNum(vector < vector < int > > & isConnected) {
        //Record the number of rows of the two-dimensional array (the two-dimensional array can be regarded as a square array in which the length and width are equal)
        int size = isConnected.size();
        //Define an array to record whether the city is accessed
        vector < int > temp(size);
        //Record number of provinces
        int res = 0;
        //Create a queue
        queue < int > q;
        //Visit every city
        for(int i=0;i<size;++i)
        {
            //The city has not been visited
            if( ! temp[i])
            {
                //Join the team for visited cities
                q.push(i);
                //When the queue is not empty
                while( ! q.empty())
                {
                    //Take team head node
                    int j = q.front();
                    //Change the value of the access array to mark that this city has been accessed
                    temp[j] = 1;
                    //Queue head node out of queue
                    q.pop();
                    //Find other cities connected to this city
                    for(int k = 0;k < size; ++k)
                    {
                       //If the old and new cities are connected and the new city has not been visited, it is queued
                       if(isConnected[j][k] == 1 && ! temp[k])
                       {
                           q.push(k);
                       }
                    }
                }
                //When a city finds all the cities connected to it, it forms a connected component, and the result value is added by 1
                ++res;
            }
        }
        return res;
    }
};

(3) Give a non empty two-dimensional array containing some 0 and 1   Grid. A   islands   By some adjacent   one   (representing land) composition. The "adjacent" here requires that two 1s must be adjacent horizontally or vertically. You can assume that   The four edges of the grid are surrounded by 0 (representing water). Find the largest island area in the given two-dimensional array. (if there are no islands, the returned area is 0)

  From the meaning of the question, let's find the maximum value of the connected component composed of 1 in the two-dimensional array. We can traverse each value in the two-dimensional array first. When the value is 1, we add it to the queue, and skip if it is 0. Carry out breadth first search and traversal on the nodes of each 1 in turn, find the number of 1 connected to it, and take out the maximum connected component until all points are traversed Just count. The code is posted below:

class Solution {
public: 
    int maxAreaOfIsland(vector < vector < int > > & grid) {
        //Define the four directions of node movement, which are up, down, left and right
        int dirs[4][2] = { {0,1}, {0,-1}, {1,0}, {-1,0}};
          //Defines the number of rows and columns of the array
          int m = grid.size();
          int n = grid[0].size();
          //Maximum area
          int res = 0;
          //Define queue
          queue < pair < int,int > > q;
          //Traverse each element in the array
          for(int i = 0; i < m; ++i)
          {
              for(int j = 0; j < n; ++j)
              {
                  //If the node is 0, exit the traversal
                  if(grid[i][j] == 0)
                  {
                      continue;
                  }
                  //If the element value is 1
                  else
                  {
                      //The area of the current island. Because there is an element at the beginning, the area is defined as 1
                      int temp = 1;
                      //Queue the current node
                      q.push( {i,j} );
                      //Update the node value, indicating that the node has been accessed
                      grid[i][j] = 0;
                      //Traversal when queue is not empty
                      while( !q.empty())
                      {
                          //Take out the coordinates of the team head node
                          int x = q.front().first,y = q.front().second;
                          //Team leader out of the team
                          q.pop();
                          //Traverse the up, down, left and right directions of the node
                          for(int k = 0;k < 4; ++k)
                          {
                              int mx = x+dirs[k][0];
                              int my = y+dirs[k][1];
                              //If the coordinates of the new node are reasonable and the value of the new node is 1
                              if(mx >= 0 && mx < m && my >= 0 &&my<n &&grid[mx][my] == 1)
                              {
                                  //Current island area + 1
                                  ++temp;
                                  //Queue new nodes
                                  q.push( {mx,my} );
                                  //Mark the new node as visited
                                  grid[mx][my] = 0;
                              }
                          }
                      }
                      //Continuously update the maximum island area
                      res = max(res,temp);
                  }
              }
          }
          return res;
    }
};

(3)   In a given grid, each cell can have one of the following three values:   0   Represents an empty cell;
value   one   Represents fresh orange; value   two   Represents rotten oranges. Every minute, any fresh oranges adjacent to rotten oranges (in 4 positive directions) will rot. returns the minimum number of minutes that must elapse until there are no fresh oranges in the cell. If not possible, returns  - 1.

  From the question: each rotten orange will rot the fresh oranges in the surrounding up, down, left and right positions. This is a breadth first search traversal algorithm. The final result requires to return the minimum number of minutes that must pass until there are no fresh oranges in the cell. In fact, it is the shortest path from rotten oranges to fresh oranges. The ontology uses BFS to solve the problem, and the code is as follows:

class Solution {
public:
    //Define the four directions to move the element, up, down, left and right
    int dirs[4][2] = { {1,0} , {-1,0} , {0,1} , {0,-1}};
    int orangesRotting(vector < vector < int > > & grid) 
    {
       //Define a queue
        queue < pair < int,int > > q;
        //Find the number of rows and columns of the array
        int m = grid.size();
        int n = grid[0].size();
        //Last minutes
        int res = 0;
        //Count the number of fresh oranges
        int good = 0;
        //Traverse the two-dimensional array, add rotten oranges to the queue, and count the number of fresh oranges
        for(int i = 0;i < m; ++i)
        {
            for(int j = 0; j < n; ++j)
            {
                if(grid[i][j] == 2)
                {
                    q.push( {i,j} );
                }
                else if(grid[i][j] == 1)
                {
                    good++;
                }
            }
        }   
        //If there are no fresh oranges, return 0 minutes
        if(good == 0)
        {
            return 0;
        }
        //When the queue is not empty
        while( !q.empty())
        {
           //Take out the coordinates of the team head node and let the team head out of the team
           int x = q.front().first,y = q.front().second;
           q.pop();
           //Find the nodes in the upper, lower, left and right directions of the old node respectively
           for(int k = 0; k < 4; ++k)
           {
              int mx = x + dirs[k][0];
              int my = y + dirs[k][1];
              //If the coordinates are reasonable and the new node is a fresh orange, start the decay operation
              if(mx >= 0 && mx < m && my >= 0 && my < n && grid[mx][my] == 1)
              {
                 //Queue new nodes
                 q.push( {mx,my} );
                 //The minutes required to decay to the new node is the minutes of the old node + 1, because the old and new nodes are adjacent
                 grid[mx][my] = grid[x][y] + 1;
                 //The returned node is the maximum number of minutes
                 res = max (res,grid[mx][my]);
                 //The number of fresh oranges is reduced by 1
                 good--;
              }
            }
        }
        //If there are still fresh oranges, it indicates that they are not completely rotten, i.e. return - 1
        if(good > 0)
        {
            return-1;
        }
        //If all rotten, the maximum number of minutes is returned. Because the value of rotten oranges at the beginning is 2, the number at the beginning is subtracted
         else
        {
            return res -2;
        }
    }
};

The four BFS examples are analyzed above, which are respectively based on the breadth search on the two-dimensional array. The four topics are very classic and have the same merits. I believe you can sum up your own writing methods and templates after careful reading.

If you think it is helpful to you, please give the writer a compliment and attention, which is my greatest support, thank you!

Topics: C++ Algorithm leetcode