[LeetCode] Surrounded Regions 广度搜索

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
Hide Tags
 Breadth-first Search
 
  题目是给定一个char 矩阵,将被包括的O 标记为X。
思路:
  遍历整个矩阵,如果遇到O 那么便找出全部与其相连的O,然后判断这个是否需要变换。
 
  这样的实现就是判断麻烦一些,而且会有重复判断,因为需要先找出全部的相连O,再遍历一次判断,然后遍历修改,操作有重复了,下面是我写的代码:
 
#include <vector>
#include <iostream>
#include <iterator>
using namespace std;

class Solution {
public:
    void solve(vector<vector<char> > &board) {
        int m=board.size();
        if(m<2) return;
        int n=board[0].size();
        if(n<2) return;
        vector<vector<bool> > flag;
        for(int i=0;i<m;i++)    flag.push_back(vector<bool>(n,false));
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(board[i][j]=='X')    flag[i][j]=true;
                if(board[i][j]=='O'&&flag[i][j]==false)
                    help_f(i,j,board,flag);
            }
        }
        return ;
    }
    void help_f(int i,int j,vector<vector<char> > &board,vector<vector<bool> > &flag)
    {
//        cout<<"Azhu"<<endl;
        vector<pair<int,int> > tmp;
        tmp.push_back({i,j});
        flag[i][j]=true;
        int now_idx=0,m=board.size(),n=board[0].size();
        while(now_idx<tmp.size()){
            int now_i = tmp[now_idx].first,now_j = tmp[now_idx].second;
            if(now_i-1>=0&&board[now_i-1][now_j]=='O'&&flag[now_i-1][now_j]==false){
                tmp.push_back({now_i-1,now_j});
                flag[now_i-1][now_j]=true;
            }
            if(now_i+1<m&&board[now_i+1][now_j]=='O'&&flag[now_i+1][now_j]==false){
                tmp.push_back({now_i+1,now_j});
                flag[now_i+1][now_j]=true;
            }
            if(now_j-1>=0&&board[now_i][now_j-1]=='O'&&flag[now_i][now_j-1]==false){
                tmp.push_back({now_i,now_j-1});
                flag[now_i][now_j-1]=true;
            }
            if(now_j+1<n&&board[now_i][now_j+1]=='O'&&flag[now_i][now_j+1]==false){
                tmp.push_back({now_i,now_j+1});
                flag[now_i][now_j+1]=true;
            }
            now_idx++;
        }
        bool canCapture=true;
        now_idx=0;
        while(canCapture&&now_idx<tmp.size()){
            int now_i = tmp[now_idx].first,now_j = tmp[now_idx].second;
            if(now_i==0||now_i==m-1||now_j==0||now_j==n-1)  canCapture=false;
            now_idx++;
        }
        if(canCapture){
            now_idx=0;
            while(now_idx<tmp.size()){
                int now_i = tmp[now_idx].first,now_j = tmp[now_idx].second;
                board[now_i][now_j]='X';
                now_idx++;
            }
        }
        return ;
    }
};

int main()
{
    vector<vector<char> > board{
        {{'X','X','X','O'}},
        {{'X','O','O','X'}},
        {{'X','X','X','X'}},
        {{'X','O','O','X'}}
    };
    Solution sol;
    sol.solve(board);
    for(int i=0;i<board.size();i++){
        copy(board[i].begin(),board[i].end(),ostream_iterator<char>(cout," "));
        cout<<endl;
    }

    return 0;
}
View Code
 
改进:
  注意到O 不能修改的是与边相连的时候,那么便改变下过程,从边开始,找出全部不能够变化的O,然后其余的O 变化,这样时间快很多。这个就不写了。
 
discuss 中提到并查集,看了一下,也就是讲全部的O 找出来,相连的划分成一个集合中,集合内的元素链表表示,一个接一个,这样避免了重复,而我实现是通过后台标记,并查集的时间其实更长,因为是单项链表的实现。或许有更好的实现,例如1-n 树表示,不过选用那个作为根节点,好像这题目不是很好用。
 
 
原文地址:https://www.cnblogs.com/Azhu/p/4204311.html