BFS——surrounded region

Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'.

A region is captured by flipping all 'O's into 'X's in that surrounded region.

For example,

X X X X
X O O X
X X O X
X O X X

After running your function, the board should be:

X X X X
X X X X
X X X X
X O X X

大多数人,包括笔者,看到本题第一反应就是,找出成片的 ‘O’的集合即可,只要不碰到边界。啊哦!反过来想,不碰到边界,那也就是说,我从边界出发能够到达(从上下左右四个方向)的点一定是不能被变成 ‘X’的, 显然,这是个BFS、DFS的问题了。于是笔者参考网上已有的大牛的代码,写下了如下的两个版本:

BFS:

class Solution {

public:
    void solve(vector<vector<char> > &board) {
        
        if(board.empty()) return;
        
        int row = board.size();
        int column = board[0].size();

        if(row <= 2 || column <= 2)
            return;

        //find start point
        vector<pair<int,int> > start;

//如果为O,才加入,表示从O开始BFS!!!找边界!!!

        for(int i = 0 ; i < row ; ++i)
        {
            if(board[i][column-1] == 'O' )
            {
                board[i][column-1] = 'D';
                start.push_back(make_pair(i,column-1));
            }

            if(board[i][0] == 'O' )
            {
                board[i][0] = 'D';
                start.push_back(make_pair(i,0));
            }
        }

        for(int i = 1 ; i < column - 1 ; ++i)
        {
            if(board[row-1][i] == 'O' )
            {
                board[row-1][i] = 'D';
                start.push_back(make_pair(row-1,i));
            }

            if(board[0][i] == 'O' )
            {
                board[0][i] = 'D';
                start.push_back(make_pair(0,i));
            }
        }

        
        
        //不能用迭代器,会改变start
        
        const static int PATH[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
        
        while(!start.empty())
        {
            pair<int,int> p = start.back();
            start.pop_back();
            
            for(int i = 0 ; i < 4; ++i)
            {
                int x = p.first, y = p.second;
                
                x += PATH[i][0];
                y += PATH[i][1];
                
                //为X的直接不用考虑!!为D的已经考虑过了!!!
                if(x < 0 || x >= row || y < 0 || y >= column || board[x][y] != 'O' ) continue;
                
                if(board[x][y] == 'O') 
                {
                    board[x][y] = 'D';
                    start.push_back(make_pair(x,y));
                }
            }
        }
        
        for(int i = 0 ; i < row; ++i)
        {
            for(int j = 0 ; j < column ; ++j)
            {
                if(board[i][j] == 'D')
                {
                    board[i][j] = 'O';
                }
                else 
                {
                    board[i][j] = 'X';
                }
            }
        }
        
    }
};

DFS: 比较简洁,但是在leetcode上出现的问题是,runtime error。。对于一个较大的例子,忘各位帮忙解答:

class Solution {
    
private:
void dfs(vector<vector<char> > &board, int x, int y, const int row, const int column)
{
    if(x < 0  || x >= row || y < 0 || y >= column || board[x][y] == 'O' ) return;
    board[x][y] = 'D';
    dfs(board, x-1,y , row, column);
    dfs(board, x+1,y , row, column);
    dfs(board, x,y-1 , row, column);
    dfs(board, x,y+1 , row, column);
    
}

public:
    void solve(vector<vector<char>> &board) {
        
        if(board.empty()) return;
        
        int row = board.size();
        int column = board[0].size();
        
        for(int i = 0 ; i < column ; ++i)
        {
            dfs(board, 0, i, row, column);
            dfs(board, row-1, i, row, column);
        }
        for(int i = 1 ; i < row-1 ; ++i)
        {
            dfs(board, i , 0, row , column);
            dfs(board, i, column-1, row,column);
        }
        
        for(int i = 0 ; i < row; ++i)
        {
            for(int j = 0 ; j < column ; ++j)
            {
                if(board[i][j] == 'D')board[i][j] = 'O';
                else board[i][j] = 'X';
            }
        }
    }
};


DFS算法是一种用于图遍历或树遍历的算法。其核心思想是从起点开始递归地深入每一个可能的分支,直到无法继续为止,然后回溯到上一个节点,继续尝试其他分支。 DFS算法有两种实现方式:递归实现和非递归实现(使用栈)。 递归实现的DFS算法伪代码: ``` DFS(node): if node is None: return visit(node) for child in node.children: DFS(child) ``` 非递归实现的DFS算法伪代码: ``` DFS(node): stack = [node] while stack: node = stack.pop() if node.visited: continue visit(node) node.visited = True for child in node.children: stack.append(child) ``` 其中,visit(node)表示对节点node进行操作,例如打印节点值、记录路径等。 DFS算法的时间复杂度为O(V+E),其中V为节点数,E为边数。因为每个节点和每条边都只会被访问一次。 下面是一个例题,用DFS算法求解从起点到终点的路径(leetcode 79题): 给定一个二维网格和一个单词,找出该单词是否存在于网格中。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 示例: ``` board = [ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ] 给定 word = "ABCCED", 返回 true. 给定 word = "SEE", 返回 true. 给定 word = "ABCB", 返回 false. ``` 实现代码: ```python class Solution: def exist(self, board: List[List[str]], word: str) -> bool: if not board or not board[0]: return False m, n = len(board), len(board[0]) visited = [[False] * n for _ in range(m)] directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] def dfs(i, j, k): if k == len(word): return True if i < 0 or i >= m or j < 0 or j >= n or visited[i][j] or board[i][j] != word[k]: return False visited[i][j] = True for dx, dy in directions: if dfs(i+dx, j+dy, k+1): return True visited[i][j] = False return False for i in range(m): for j in range(n): if dfs(i, j, 0): return True return False ``` 时间复杂度为O(m*n*3^k),其中m、n为网格大小,k为单词长度。因为每个格子都有可能走,所以是O(m*n),而每次调用dfs函数会向四个方向递归,每个方向都不能重复走,所以是3^k。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值