思考:只要将被包围的O和未被包围的O分开就好
方法
- 1、用并查集(Union-find set)来区分,然后对原数组更改即可
- 2、用BFS将与边缘O相邻的O(为被包围的O)全部变为#(或者其他符号),然后对原数组做相应更改
代码块
并查集
public class Solution {
int[] unitArray; //集合编号(隶属于哪一类)
boolean[] edge; //是否被包围,每一类的edge都应该相同
public void solve(char[][] board) {
if(board.length < 3 || board[0].length < 3)
return;
unitArray = new int[board.length * board[0].length];
edge = new boolean[unitArray.length];
//initial the array
for (int i = 0; i < unitArray.length; i++)
unitArray[i] = i;
for (int i = 0; i < unitArray.length; i++) {
int r = i / board[0].length;
int c = i % board[0].length;
edge[i] = (board[r][c] == 'O' &&
(r == 0 || r == board.length - 1
|| c == 0 || c == board[0].length - 1)); // true表示没有被包围
}
// span the matrix
for (int i = 0; i < unitArray.length; i++) {
int r = i / board[0].length;
int c = i % board[0].length;
int up = r - 1;
int pre = c - 1;
//the unper field
if (up >= 0 && board[r][c] == board[up][c])
unit(i, i - board[0].length); //应该属于一类,unit一下
//the pre field
if (pre >=0 && board[r][c] == board[r][pre])
unit(i, i - 1);
}
for (int i = 0; i < unitArray.length; i++) {
int r = i / board[0].length;
int c = i % board[0].length;
if (board[r][c] =='O' && !edge[find(i)])
board[r][c] = 'X';
}
}
private void unit(int x, int y) {
int rootX = find(x); //找到这一类的根
int rootY = find(y);
boolean edgeU = this.edge[rootX] || this.edge[rootY]; //只要有一个被包围,则都被包围
unitArray[rootX] = rootY;
this.edge[rootY] = edgeU;
}
private int find(int x) {
if (unitArray[x] == x) return x;
unitArray[x] = find(unitArray[x]);
return unitArray[x];
}
}
BFS方法
public class Solution {
public void solve(char[][] board) {
if(board.length < 3 || board[0].length < 3)
return;
int n = board.length;
int m = board[0].length;
Queue<Integer> queue = new LinkedList<Integer>();
//将四周的O,加入队列
for(int i = 0; i < n; i++){
if(board[i][0] == 'O')
queue.add(i * m);
if(board[i][m - 1] == 'O')
queue.add(i * m + m - 1);
}
for(int j = 1; j < m - 1; j++){
if(board[0][j] == 'O')
queue.add(j);
if(board[n - 1][j] == 'O')
queue.add((n - 1) * m + j);
}
//BFS遍历,将没有被包围的O置为#
BFS(queue, board);
//留下来的O都是被包围的
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++){
if(board[i][j] == '#')
board[i][j] = 'O';
else if (board[i][j] == 'O')
board[i][j] = 'X';
}
}
void BFS(Queue<Integer> queue, char[][] board){
int m = board[0].length;
int n = board.length;
while(!queue.isEmpty()){
int value = queue.poll();
int row = value / m ;
int col = value % m ;
board[row][col] = '#';
if(row - 1 >= 0 && board[row - 1][col] == 'O')
queue.add((row - 1) * m + col);
if(row + 1 < n && board[row + 1][col] == 'O')
queue.add((row + 1) * m + col);
if(col - 1 >= 0 && board[row][col - 1] == 'O')
queue.add(row * m + col - 1);
if(col + 1 < m && board[row][col + 1] == 'O')
queue.add(row* m + col + 1);
}
}
}