这题的思路和lc-200有相似之处,依旧是通过 DFS(或 BFS)来“遍历连通区域并做标记”。但与 200 不同的是,这道题需要我们区分 “被包围的 O” 和 “未被包围的 O” 。
解题思路
-
首先从边界出发,将所有与边界
'O'相连的'O'都标记为'#'; -
然后遍历整个棋盘:
- 剩余的
'O'就是被包围的,修改为'X'; - 标记过的
'#'恢复为'O'。
- 剩余的
DFS
var solve = function (board) {
let row = board.length;
let col = board[0].length;
var dfs = function (i, j) {
if (i < 0 || i >= row || j < 0 || j >= col) return;
if (board[i][j] !== "O") return;
board[i][j] = "#";
dfs(i, j - 1);
dfs(i, j + 1);
dfs(i - 1, j);
dfs(i + 1, j);
};
// 左右边界修改为 #
for (let i = 0; i < row; ++i) {
dfs(i, 0);
dfs(i, col - 1);
}
// 上下边界修改为 #
for (let j = 0; j < col; ++j) {
dfs(0, j);
dfs(row - 1, j);
}
for (let i = 0; i < row; ++i) {
for (let j = 0; j < col; ++j) {
if(board[i][j] === 'O'){
// 内部的 O 改为 X
board[i][j] = 'X'
}else if(board[i][j] === '#'){
// 还原
board[i][j] = 'O'
}
}
}
};
BFS
var solve = function (board) {
let row = board.length;
let col = board[0].length;
let directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]
var bfs = function (i, j) {
// 保证边界上是 O 开始
if(board[i][j] !== 'O') return
board[i][j] = '#';
let queue = [[i, j]]
while(queue.length){
let [x, y] = queue.shift()
for(let [dx, dy] of directions){
let fx = dx + x
let fy = dy + y
if(fx >= 0 && fx < row && fy >= 0 && fy < col && board[fx][fy] === 'O'){
queue.push([fx, fy])
board[fx][fy] = '#'
}
}
}
};
// 左右边界修改为 #
for (let i = 0; i < row; ++i) {
bfs(i, 0);
bfs(i, col - 1);
}
// 上下边界修改为 #
for (let j = 0; j < col; ++j) {
bfs(0, j);
bfs(row - 1, j);
}
for (let i = 0; i < row; ++i) {
for (let j = 0; j < col; ++j) {
if(board[i][j] === 'O'){
// 内部的 O 改为 X
board[i][j] = 'X'
}else if(board[i][j] === '#'){
// 还原
board[i][j] = 'O'
}
}
}
};
✅ DFS vs BFS 对比
| 方式 | 原理 | 特点 | 推荐使用场景 |
|---|---|---|---|
| DFS | 递归遍历 | 实现简单,但递归深度大时可能栈溢出 | 连通性判断、路径查找 |
| BFS | 队列逐层扩展 | 更适合最短路径、多点并发扩展 | 需要层次处理的题目,如迷宫、岛屿 |