【LeetCode】Surrounded Region

Surrounded Region 跟 Num of Islands 同类思路。唯一不同的是,对四条边的边界点的判定标准不同。前者认为,边界点不是被包围的点,后者认为是。

我一直都不习惯递归的算法,所以很多遍历题都用了stack或者queue来一步一步遍历。

这题的思路是:你可以选择检测被包围的区域,也可以选择不被包围的区域。显然,由于不被包围的区域都是与四周边界点相关的,所以后者的速度更快些。

【我的思路是】:遍历整个board,检测被包围的区域,BFS+queue (40+ms)

class Solution {
public:
    void solve(vector<vector<char>>& board) {
        if(board.empty()||board[0].empty())
            return ;
        vector<vector<char>> & b=board; //拷贝一个board 的副本。在board上修改,用b来判断包围区域。
        vector<vector<bool>> visit(board.size(),vector<bool>(board[0].size(),false));
        queue<pair<int,int>> qu;
        vector<vector<int>> dir(4,vector<int>(2));
        dir[0][0]=-1;dir[0][1]=0;dir[1][0]=1;dir[1][1]=0;dir[2][0]=0;dir[2][1]=-1;dir[3][0]=0;dir[3][1]=1;
        int i,j,k;
        int row=b.size(),col=b[0].size();
        for(i=0;i<row;i++){
            for(j=0;j<col;j++){
                if(b[i][j]=='X'||visit[i][j])
                    continue;
                qu.push(make_pair(i,j));
                visit[i][j]=true;
                bool sur=true;
                vector<pair<int,int>> pos;
                while(!qu.empty()){
                    pair<int,int>p=qu.front();
                    if(p.first==0||p.first==row-1||p.second==0||p.second==col-1) 
                        sur=false; //<span style="font-family: Arial, Helvetica, sans-serif;">发现这块都是‘O’的区域有边界点,所以不是合法的surrounded region。即便如此,我们也要把这整块区域找出来,以便防止它干扰其他区域的判断。</span>

                    pos.push_back(p);
                    qu.pop();
                    for(k=0;k<dir.size();k++){
                        int first=dir[k][0]+p.first;
                        int second=dir[k][1]+p.second;
                        if(first>=0&&first<row&&second>=0&&second<col&&b[first][second]=='O'&&!visit[first][second]){
                            visit[first][second]=true;
                            qu.push(make_pair(first,second));
                        }
                    }
                }
                if(sur){ //找到了surrounded region,capture 它。
                    for(k=0;k<pos.size();k++){
                        board[pos[k].first][pos[k].second]='X';
                    }
                }
                pos.clear();
            }
        }
    }
};


检测不合法的包围区域,显得更省空间更高效:不必复制board的副本,而且速度快。(20+ms)

遍历四周的边界点,把不合法的包围区域暂时mark为其他字符,比如‘M’。BFS+queue

再遍历整个board,如果检测到‘M’,复原成‘O’;如果检测到‘O’,说明是没被mark过的,即合法的包围区域,复制为‘X’

void mark(vector<vector<char>> & board,int ii,int jj){
    	queue<pair<int,int>> qu;
    	board[ii][jj]='M'; 
    	qu.push(make_pair(ii,jj));
    	int i,j,k;
    	int row=board.size(),col=board[0].size();
    	vector<vector<int>> dir(4,vector<int>(2));
    	dir[0][0]=0;dir[0][1]=1;
    	dir[1][0]=0;dir[1][1]=-1;
    	dir[2][0]=1;dir[2][1]=0;
    	dir[3][0]=-1;dir[3][1]=0;
    
    	while(!qu.empty()){
    		pair<int,int> p=qu.front();
    		qu.pop();
    		for(k=0;k<dir.size();k++){
    			int first=dir[k][0]+p.first;
    			int second=dir[k][1]+p.second;
    			if(first>=0&&first<row&&second>=0&&second<col&&board[first][second]=='O'){
    				board[first][second]='M';
    				qu.push(make_pair(first,second));
    			}
    		}
    	}
    }

    void solve(vector<vector<char>>& board){
    	if(board.empty()||board[0].empty())
    		return ;
    	int row=board.size();
    	int col=board[0].size();
    	int i,j,k;
<span style="white-space:pre">	</span>// 遍历四条边,检测不合法的包围区域并mark
    	for(i=0;i<col;i++){
    		if(board[0][i]=='O')
    			mark(board,0,i);
    		if(board[row-1][i]=='O')
    			mark(board,row-1,i);
    	}
    	for(i=0;i<row;i++){
    		if(board[i][0]=='O')
    			mark(board,i,0);
    		if(board[i][col-1]=='O')
    			mark(board,i,col-1);
    	}
    <span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>// 遍历整个board,复原不合法的包围区域+capture合法包围区域
    	for(i=0;i<row;i++){
    		for(j=0;j<col;j++){
    			if(board[i][j]=='O')
    				board[i][j]='X';
    			else if(board[i][j]=='M')
    				board[i][j]='O';
    		}
    	}
    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值