leetcode算法总结 —— DFS之网格类问题

网格类DFS

我把此类问题归纳为网格类的DFS,典型例题为岛屿标记,下面是该体型类模版,类似题都是根据该模版变形。
模板

1. 遍历过的岛屿需要标记

class Solution {
    
    
public:
    int numIslands(vector<vector<char>> &grid)
    {
    
    
        int count = 0;
        if (grid.size() == 0) return 0;
        //遍历网格
        for(int i = 0; i < grid.size(); i++) {
    
    
            for(int j = 0; j < grid[i].size(); j++) {
    
    
                //如果该格子是1,则该1进行dfs得到连接的所有1组成一个岛屿
                if(grid[i][j] == '1') {
    
    
                    dfs(grid, i, j);
                    count++;//组成岛屿后岛屿数量加一
                }
            }
        }
        return count;
    }
    void dfs(vector<vector<char>> &grid, int row, int col) {
    
    
        //判断是否到边界,超过边界则return
        if(row < 0 || row > grid.size()-1 || col < 0 || col > grid[0].size()-1) return;

        //如果当前为1则我们把它标记为2, 如果不是1则我们就return,该点不继续递归
        //这里走过的要做标记是为了防止回头遍历,走过的就不走了
        if(grid[row][col] == '1') grid[row][col] = '2';
        else return;

        //上下左右递归
        dfs(grid, row-1, col);
        dfs(grid, row+1, col);
        dfs(grid, row, col-1);
        dfs(grid, row, col+1);
    }

};
    1. 岛屿数量
    1. 岛屿的周长
    1. 岛屿的最大面积
    1. 不同岛屿的数量
    1. 图像渲染
    1. 被围绕的区域
  • 剑指 Offer 13. 机器人的运动范围

2. 遍历过的岛屿需要再次使用的情况

上述几个题遍历过的岛屿标记后就不会再次遍历,而下面几题会在标记后再次使用,这就需要在后序遍历处使用回溯,将已标记的岛屿撤销标记

        //如果当前岛屿的下一个岛屿返回true也就是找到了,则可以返回了,不需要继续递归了
        if( dfs(board, row-1, col, index) ||
        dfs(board, row+1, col, index) ||
        dfs(board, row, col-1, index) ||
        dfs(board, row, col+1, index) == true) {
    
    
            return true;
        }

        //回溯:这里是后序遍历执行代码,也就是说我们DFS一条ABC之后,会往回走一遍,也就是向父节点返回
        //当往回走的时候,我们把当前节点值还原成原字符,因为后面再次查找路径的时候会使用该字符
        board[row][col] = temp;
        return false;
    }
    1. 单词搜索(注意这里要判断下一个岛屿,不然超时)

猜你喜欢

转载自blog.csdn.net/chongbin007/article/details/114040339