现在有一个仅包含‘X’和‘O’的二维板,请捕获所有的被‘X’包围的区域
捕获一个被包围区域的方法是将被包围区域中的所有‘O’变成‘X’
例如
X X X X X O O X X X O X O X X X执行完你给出的函数以后,这个二维板应该变成:
X X X X X X X X X X X X O X X X
/* * 所有与四条边相连的O都保留,其他O都变为X * 遍历四条边上的O,并深度遍历与其相连的O,将这些O都转为* * 将剩余的O变为X * 将剩余的*变为O */ public int rowNum = 0; public int colNum = 0; public void solve(char[][] board) { if(board == null || board.length <= 0|| board[0].length <= 0){ return; } rowNum = board.length; colNum = board[0].length; for(int i = 0; i < colNum; i++){ dfs(board, 0, i); dfs(board, rowNum-1, i); } for(int i = 0; i < rowNum; i++){ dfs(board, i, 0); dfs(board, i, colNum-1); } for(int i = 0; i < rowNum; i++){ for(int j = 0; j < colNum; j++){ if(board[i][j] == 'O'){ board[i][j] = 'X'; } } } for(int i = 0; i < rowNum; i++){ for(int j = 0; j < colNum; j++){ if(board[i][j] == '*'){ board[i][j] = 'O'; } } } } private void dfs(char[][] board, int row, int col) { // TODO Auto-generated method stub if(board[row][col] == 'O'){ board[row][col] = '*'; if(row > 1){ dfs(board, row-1, col); } if(col > 1){ dfs(board, row, col-1); } if(row < rowNum-1){ dfs(board, row+1, col); } if(col < colNum-1){ dfs(board, row, col+1); } } }
也是一楼的思路
从四周的'O'开始深度优先搜索 将其标记为'a'
然后将剩下的'O'变成X
最后将'a'变回'O'
class Solution {
public:
void dfs(vector<vector<char>> &board, int row, int col,
int x, int y){
int stepx[4] = {1, -1, 0, 0}; //用数组保存路径
int stepy[4] = {0, 0, 1, -1}; //吐槽一下C++这种在类里面的题目没法用全局变量
if(board[x][y] == 'O'){
board[x][y] = 'a';
for(int i = 0; i < 4; i++){ //上下左右四个方向搜索
if(x + stepx[i] >= 0 && x + stepx[i] < row &&
y + stepy[i] >= 0 && y + stepy[i] < col &&
board[x + stepx[i]][y + stepy[i]] == 'O'){
dfs(board, row, col, x + stepx[i], y + stepy[i]);
}
}
}
}
void solve(vector<vector<char>> &board) {
int row = board.size(); if(row == 0) return; //防止出很贱的测试样例
int col = board[0].size();
for(int i = 0; i < col; i++) dfs(board, row, col, 0, i); //第一行
for(int i = 0; i < col; i++) dfs(board, row, col, row - 1, i); //最后一行
for(int i = 0; i < row; i++) dfs(board, row, col, i, 0); //第一列
for(int i = 0; i < row; i++) dfs(board, row, col, i, col - 1); //最后一列
for(int i = 0; i < row; i++)
for(int j = 0; j < col; j++){
if(board[i][j] == 'O') board[i][j] = 'X';
if(board[i][j] == 'a') board[i][j] = 'O';
}
}
};
//感谢一楼的思路,自己再理解一下,就是O能找到出口的问题,然后从出口处的O反过来去找 //出来的路径。 public class Solution { public void DFS(char[][] board, int row, int col) { if(row < 0 || row>(board.length - 1) || col < 0 || col >(board[0].length -1) ) return ; if(board[row][col] == 'O') { board[row][col] = '*'; DFS(board, row-1,col); DFS(board,row+1,col); DFS(board,row,col-1); DFS(board,row,col+1); } } public void solve(char[][] board) { if(board.length <= 0) return; int row = board.length; int col = board[0].length; for(int i = 0 ; i != row ; i++) { DFS(board,i,col-1); DFS(board,i,0); } for(int i = 0 ; i != col ;i++) { DFS(board,0,i); DFS(board,row-1,i); } for(int i = 0 ; i != row ; i++) for(int j = 0 ; j != col ; j++) { if(board[i][j] == 'O') board[i][j] = 'X'; if(board[i][j] == '*') board[i][j] = 'O'; } } }
public class Solution { public void solve(char[][] board) { if(board.length == 0) return; int[][] direction = {{1, 0}, { - 1, 0}, {0, 1}, {0, - 1}}; // 第一行 for (int i = 0; i < board[0].length; i ++ ) { if(board[0][i] == 'O') { board[0][i] = '*'; dfs(board, 0, i, direction); } } // 最后一行 for (int i = 0; i < board[0].length; i ++ ) { if(board[board.length - 1][i] == 'O') { board[board.length - 1][i] = '*'; dfs(board, board.length - 1, i, direction); } } // 第一列 for (int i = 0; i < board.length; i ++ ) { if(board[i][0] == 'O') { board[i][0] = '*'; dfs(board, i, 0, direction); } } // 最后一列 for (int i = 0; i < board.length; i ++ ) { if(board[i][board[0].length - 1] == 'O') { board[i][board[0].length - 1] = '*'; dfs(board, i, board[0].length - 1, direction); } } // *变O,O变X for (int i = 0; i < board.length; i ++ ) { for (int j = 0; j < board[0].length; j ++ ) { if(board[i][j] == 'O') board[i][j] = 'X'; else if(board[i][j] == '*') board[i][j] = 'O'; } } } public static void dfs(char[][] board, int x, int y, int[][] direction) { for (int i = 0; i < direction.length; i ++ ) { int nx = x + direction[i][0]; int ny = y + direction[i][1]; if(nx >= 0 && nx < board.length && ny >= 0 && ny < board[0].length && board[nx][ny] == 'O') { board[nx][ny] = '*'; dfs(board, nx, ny, direction); } } } }
class Solution { public: void solve(vector<vector<char>> &board) { if (board.empty()) return; const int m = board.size(), n = board[0].size(); for (int x = 0; x < n; ++x) DFS(board, m, n, x, 0), DFS(board, m, n, x, m - 1); for (int y = 0; y < m; ++y) DFS(board, m, n, 0, y), DFS(board, m, n, n - 1, y); unordered_map<char, char> mp{{'#', 'O'}, {'O', 'X'}, {'X', 'X'}}; for (int y = 0; y < m; ++y) for (int x = 0; x < n; ++x) board[y][x] = mp[board[y][x]]; } private: void DFS(vector<vector<char>>& board, int m, int n, int x, int y) { if (x < 0 || x == n || y < 0 || y == m || board[y][x] != 'O') return; board[y][x] = '#'; DFS(board, m, n, x - 1, y); DFS(board, m, n, x + 1, y); DFS(board, m, n, x, y - 1); DFS(board, m, n, x, y + 1); } };
public class Solution { public void solve(char[][] board) { /** * 由题目可以知道,只要与边界上"O"连通的"O"都不能被替换 * 反之,我们可以遍历边界上的"O",从每一个边界的"O"开始 * 递归遍历与其连通的"O",并标记出来 * 最后把标记的"O"保留,未标记的"O"替换为"X" * 一共遍历两次,时间复杂度O(n),未使用额外存储空间 * 容易出错的地方,数组下标和二维空间坐标正好是反过来的,注意转化 * 另外数组不一定是正方形,长和宽不一定相等 **/ if(board.length < 1) return; int m = board.length; int n = board[0].length; // 只有边缘元素不需要处理 if(n<3||m<3){ return; } // 遍历上边缘 for(int i=0,j=0; j<n; j++){ if(board[i][j]=='O'){ spread(board, i, j); } } // 遍历右边缘 for(int j=n-1,i=0; i<m; i++){ if(board[i][j]=='O'){ spread(board, i, j); } } // 遍历下边缘 for(int j=n-1,i=m-1; j>=0; j--){ if(board[i][j]=='O'){ spread(board, i, j); } } // 遍历左边缘 for(int j=0,i=m-1; i>=0; i--){ if(board[i][j]=='O'){ spread(board, i, j); } } // 替换'A'和'O' for(int i=0; i<m; i++){ for(int j=0; j<n; j++){ if(board[i][j]=='O'){ board[i][j]='X'; } if(board[i][j]=='A'){ board[i][j]='O'; } } } } public static void spread(char[][] board, int x, int y){ int m = board.length; int n = board[0].length; // 标记 board[x][y] = 'A'; if(x-1>=0&&board[x-1][y]=='O'){ spread(board, x-1, y); } if(x+1<m&&board[x+1][y]=='O'){ spread(board, x+1, y); } if(y-1>=0&&board[x][y-1]=='O'){ spread(board, x, y-1); } if(y+1<n&&board[x][y+1]=='O'){ spread(board, x, y+1); } } }
class Solution { public: void infect(vector<vector<char>>&board,int row,int col,char identify,char target){ if(row<0||row>=board.size()||col<0||col>=board[0].size()||board[row][col]!=identify)return; board[row][col]=target; infect(board,row+1,col,identify,target); infect(board,row,col+1,identify,target); infect(board,row,col-1,identify,target); infect(board,row-1,col,identify,target); } void boarderChange(vector<vector<char>>&board,char identify,char target){ for(int i=0;i<board.size();i++){ infect(board,i,0,identify,target); infect(board,i,board[0].size()-1,identify,target); } for(int i=0;i<board[0].size();i++){ infect(board,0,i,identify,target); infect(board,board.size()-1,i,identify,target); } } void solve(vector<vector<char>> &board) { //先从边界走起,为O的圈改为1,然后遍历整个表,为圈的感染一块全变为x,最后将1还原为O //看起来复杂度高,实际复杂度是O(n)的 if(board.empty())return; boarderChange(board,'O','1'); //--------------------------------------- for(int i=1;i<board.size()-1;i++) for(int j=1;j<board[0].size()-1;j++) infect(board,i,j,'O','X'); boarderChange(board,'1','O'); } };
从不可能被包围的圆圈突破,献上比较简短的代码 class Solution { public: int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; void dfs(int x,int y,vector<vector<char>> &board){ int m = board[0].size(); int n = board.size(); if(board[x][y]!='O') return; board[x][y]='B'; for(int i=0;i<4;i++){ int nx=x+dx[i]; int ny = y+dy[i]; if(nx>=0&&nx<n&&ny>=0&&ny<m){ dfs(nx,ny,board); } } } void solve(vector<vector<char>> &board) { if(board.size()==0) return; int m = board[0].size(); int n = board.size(); // cout<<n<<' '<<m<<endl; for(int i=0;i<n;i++){ dfs(i,0,board); dfs(i,m-1,board); } for(int j=0;j<m;j++){ dfs(0,j,board); dfs(n-1,j,board); } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(board[i][j]=='O') board[i][j]='X'; else if(board[i][j]=='B') board[i][j]='O'; } } } };
/**
* 1.矩阵四边的O皆不符合条件,所以我们把O以及与O连接的点标记为* 2.接着修改剩余的O值为X 3.将没有被包围的点(*)恢复为O
*/
public class Solution {
public void solve(char[][] board) {
if (board == null || board.length < 3 || board[0].length < 3) {
return;
}
int rows = board.length;
int cols = board[0].length;
for (int i = 0; i < rows; i++) {
dfs(board, i, rows, 0, cols); // 左边界
dfs(board, i, rows, cols - 1, cols); // 右边界
}
for (int j = 0; j < cols; j++) {
dfs(board, 0, rows, j, cols); // 上边界
dfs(board, rows - 1, rows, j, cols); // 下边界
}
for(int i = 0; i < rows ; i++){
for(int j = 0; j < cols; j++){
if(board[i][j] == 'O'){
board[i][j] = 'X';
}else if(board[i][j] == '*'){
board[i][j] = 'O';
}
}
}
}
public void dfs(char[][] board, int row, int rows, int col, int cols) {
if (row < 0 || row >= rows || col < 0 || col >= cols) {
return;
}
if (board[row][col] == 'O') {
board[row][col] = '*';
dfs(board, row + 1, rows, col, cols);
dfs(board, row - 1, rows, col, cols);
dfs(board, row, rows, col + 1, cols);
dfs(board, row, rows, col - 1, cols);
}
}
}
public void solve(char[][] board) {
if (board == null || board.length == 0) {
// print(board);
return;
}
//上边
for (int i = 0; i < board[0].length; i++) {
if (board[0][i] == 'O') {
board[0][i] = '*';
if (board.length != 1) {
dfs(board, 1, i);
}
}
}
//右边
for (int i = 0; i < board.length; i++) {
if (board[i][board[0].length - 1] == 'O') {
board[i][board[0].length - 1] = '*';
if (board.length != 1) {
dfs(board, i, board[0].length - 2);
}
}
}
//下面
for (int i = 0; i < board[0].length; i++) {
if (board[board.length - 1][i] == 'O') {
board[board.length - 1][i] = '*';
if (board.length != 1) {
dfs(board, board.length - 2, i);
}
}
}
//左边
for (int i = 0; i < board.length; i++) {
if (board[i][0] == 'O') {
board[i][0] = '*';
if (board.length != 1) {
dfs(board, i, 1);
}
}
}
clean(board);
// print(board);
}
private void clean(char[][] board) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == 'O') {
board[i][j] = 'X';
}
if (board[i][j] == '*') {
board[i][j] = 'O';
}
}
}
}
private void dfs(char[][] board, int row, int col) {
if (board[row][col] == 'O') {
board[row][col] = '*';
if (col != 0) {
dfs(board, row, col - 1);
}
if (col != board[0].length - 1) {
dfs(board, row, col + 1);
}
if (row != 0) {
dfs(board, row - 1, col);
}
if (row != board.length - 1) {
dfs(board, row + 1, col);
}
}
}
class Solution {
public:
void solve(vector<vector<char>> &board) {
if(board.size()<=0 || board[0].size()<=0) return ;
int row=board.size(),col=board[0].size();
vector<vector<bool> >dp(row,vector<bool>(col,false));
stack<vector<int> >S;
vector<int> tmp(2,0);
for(int i=0;i<row;++i){
for(int j=0;j<col;++j){
if((i==0 || i==row-1 || j==0 ||j==col-1) && board[i][j]=='O' && dp[i][j]==false){
dp[i][j]=true;
tmp[0]=i;
tmp[1]=j;
S.push(tmp);
while(!S.empty()){
int m=S.top()[0],n=S.top()[1];
if(m-1>=0 && dp[m-1][n]==false && board[m-1][n]=='O'){
dp[m-1][n]=true;
tmp[0]=m-1;
tmp[1]=n;
S.push(tmp);
}
if(m+1<row && dp[m+1][n]==false && board[m+1][n]=='O'){
dp[m+1][n]=true;
tmp[0]=m+1;
tmp[1]=n;
S.push(tmp);
}
if(n-1>0 && dp[m][n-1]==false && board[m][n-1]=='O'){
dp[m][n-1]=true;
tmp[0]=m;
tmp[1]=n-1;
S.push(tmp);
}
if(n+1<col && dp[m][n+1]==false && board[m][n+1]=='O'){
dp[m][n+1]=true;
tmp[0]=m;
tmp[1]=n+1;
S.push(tmp);
}
m=S.top()[0],n=S.top()[1];
if(!(m-1>=0 && dp[m-1][n]==false && board[m-1][n]=='O' || m+1<row && dp[m+1][n]==false && board[m+1][n]=='O' || n-1>0 && dp[m][n-1]==false
&& board[m][n-1]=='O' || n+1<col && dp[m][n+1]==false && board[m][n+1]=='O'))
S.pop();
}
}
}
}
for(int i=1;i<row-1;++i){
for(int j=1;j<col-1;++j){
if(board[i][j]=='X' || dp[i][j]==false) board[i][j]='X';
else board[i][j]='O';
}
}
}
};
class Solution { int book[200][200],n,m,next[4][2]={1,0,-1,0,0,1,0,-1}; public: void solve(vector<vector<char>> &board) { n=board.size(); if(n==0) return; m=board[0].size(); int i,j; memset(book,0,sizeof(book)); for(i=1;i<n-1;i++) dfs(i,0,board,'+'),dfs(i,m-1,board,'+'); for(j=0;j<m;j++) dfs(0,j,board,'+'),dfs(n-1,j,board,'+'); memset(book,0,sizeof(book)); for(i=0;i<n;i++) for(j=0;j<m;j++) dfs(i,j,board,'X'); for(i=0;i<n;i++) for(j=0;j<m;j++) if(board[i][j]=='+') board[i][j]='O'; } void dfs(int x,int y,vector<vector<char>> &board,char isp){ if(x<0||x>=n||y<0||y>=m) return; if(board[x][y]!='O') return; if(book[x][y]) return; book[x][y]=1,board[x][y]=isp; for(int i=0;i<4;i++) dfs(x+next[i][0],y+next[i][1],board,isp); } };
思路:首先将边界上的O以及与边界O相连的O都标记为N, 然后将其他的O都变为X,最后将N重新变为O即可 public void solve(char[][] board) { if (board == null || board.length == 0 || board[0].length == 0) { return; } int row = board.length; int column = board[0].length; for (int i = 0; i < row; i++) { dfs(board, i, 0); dfs(board, i, column - 1); } for (int i = 0; i < column; i++) { dfs(board, 0, i); dfs(board, row - 1, i); } for (int i = 0; i < row; i++) { for (int j = 0; j < column; j++) { if(board[i][j]=='O'){ board[i][j]='X'; } if(board[i][j]=='N'){//把标记为N的重新变为O board[i][j]='O'; } } } } // 将边界上的O变为N,与边界O相连的所有O都变为N,N是一个标记表示不可变的O private void dfs(char[][] board, int i, int j) { int row = board.length; int column = board[0].length; if (i < 0 || i >= row || j < 0 || j >= column) { return; } if (board[i][j] == 'X') { return; } if (board[i][j] == 'O') { board[i][j] = 'N'; dfs(board, i + 1, j); dfs(board, i - 1, j); dfs(board, i, j + 1); dfs(board, i, j - 1); } }
class Solution { public: void solve(vector<vector<char>> &board) { if(board.empty()) return; int rows = board.size(); int cols = board[0].size(); if(rows==0 || cols==0) return; for(int j=0;j<cols;j++) { DFS(board, 0, j); DFS(board, rows-1, j); } for(int i=0;i<rows;i++) { DFS(board, i, 0); DFS(board, i, cols-1); } for(int i=0;i<rows;i++) for(int j=0;j<cols;j++) if(board[i][j] == 'O') board[i][j] = 'X'; for(int i=0;i<rows;i++) for(int j=0;j<cols;j++) if(board[i][j] == '*') board[i][j] = 'O'; } void DFS(vector<vector<char> > &board, int r, int c) { if(board[r][c] == 'O') { board[r][c] = '*'; int rows = board.size(); int cols = board[0].size(); if(r > 1) DFS(board, r-1, c); if(r < rows-2) DFS(board, r+1, c); if(c > 1) DFS(board, r, c-1); if(c < cols-2) DFS(board, r, c+1); } } };
//从四条边开始搜索,遇到“O”就在满足边界条件下进行深度搜索,递归调用搜索函数 #include<vector> #include<iostream> using namespace std; const int CONST_COL = 5; class surrounded_regions { public: void solve(vector<vector<char>> &board) { int row = board.size(); int col = board[0].size(); if(row <= 2 || col <= 2) return; for(int i = 0; i < row; i++){ for(int j = 0; j < col; j++){ if((board[i][j] == 'O' && i == 0) || (board[i][j] == 'O' && i == row - 1)) dfs(board, i, j); else if((board[i][j] == 'O' && j == 0) || (board[i][j] == 'O' && j == col - 1)) dfs(board, i, j); } } getResult(board); } private: void dfs(vector<vector<char>> &board, int Row, int Col){ if(board[Row][Col] == 'O'){ board[Row][Col] = '*'; if(Row - 1 >= 0) dfs(board, Row - 1, Col); if(Row + 1 <= board.size()-1) dfs(board, Row + 1, Col); if(Col - 1 >= 0) dfs(board, Row, Col - 1); if(Col + 1 < board[0].size()) dfs(board, Row, Col + 1); } else return; } void getResult(vector<vector<char>> &board){ for(int row = 0; row < board.size(); row++) for(int col = 0; col < board[0].size(); col++){ if(board[row][col] == '*') board[row][col] = 'O'; else if(board[row][col] == 'O') board[row][col] = 'X'; } } }; int main() { char arr[][CONST_COL] = {'O','X','X','O','X', 'X','O','O','X','O', 'X','O','X','O','X', 'O','X','O','O','O', 'X','X','O','X','O'}; vector<vector<char>> board; for(int i = 0; i < CONST_COL; i++){ vector<char> tempArr; for(int j = 0; j < CONST_COL; j++){ tempArr.push_back(arr[i][j]); } board.push_back(tempArr); } surrounded_regions SR; SR.solve(board); for(auto ivec = board.cbegin(); ivec != board.cend(); ivec++){ for(auto jvec = ivec->cbegin(); jvec != ivec->cend(); jvec++){ cout << *jvec << " "; } cout << endl; } system("pause"); return 0; }
思路1:看了各位大神的思路都是从四周‘O’入手深度搜索,
搜到的‘O’标记为‘*’,然后剩下的‘O’都是被包围的,
置为‘X’。
思路2:我是遍历每一个点,当遍历到‘O’的时候,进行深搜,
看能不能找到边界,如果可以表示该位置没有被包围,
否则,被包围,置为‘X’。
下面是代码,错误提示:存在数组越界非法访问等情况。
那个大神给瞅一眼,咋就非法访问了呢? public class Solution {
public static void solve(char[][] board){
if (board == null || board.length <= 2 || board[0].length <= 2)
return;
int x = board.length;
int y = board[0].length;
for(int i=0;i<x;i++){
for(int j=0;j<y;j++){
if(board[i][j] == 'O'){
if(dfs(board, i, j)){
board[i][j] = 'X';
}
}
}
}
}
public static boolean dfs(char[][] board, int x, int y){
int lenx = board.length;
int leny = board[0].length;
int[][] d = {{0,1},{1,0},{0,-1},{-1,0}};
for(int i=0;i<4;i++){
int newx = x+d[i][0];
int newy = y+d[i][1];
if((newx >=0 && newx < lenx)
&& (newy >= 0 && newy < leny)){
if(board[newx][newy] == 'O'){
board[newx][newy] = '*';
if(dfs(board, newx, newy) == false){
board[newx][newy] = 'O';
return false;
}
board[newx][newy] = 'O';
}
}else
return false;
}
return true;
}
}