【每天学习一点算法 2026/05/15】被围绕的区域
每天学习一点算法 2026/05/15题目被围绕的区域给你一个 m x n 的矩阵 board 由若干字符 ‘X’ 和 ‘O’ 组成捕获 所有 被围绕的区域连接一个单元格与水平或垂直方向上相邻的单元格连接。区域连接所有 ‘O’ 的单元格来形成一个区域。围绕如果一个区域中的所有 ‘O’ 单元格都不在棋盘的边缘则该区域被包围。这样的区域 完全 被 ‘X’ 单元格包围。通过 原地 将输入矩阵中的所有 ‘O’ 替换为 ‘X’ 来 捕获被围绕的区域。你不需要返回任何值。这道题的思路还是很简单的首先遍历矩阵遇到 ‘O’ 时开始递归遍历完所有相邻的 ‘O’如果过程没有碰到边界就将这些 ‘O’ 替换成 ‘X’否则就不做操作。functionsolve(board:string[][]):void{constvisitednewSetstring();// 存储访问过的位置constosetnewSetstring();// 存储当前遍历相邻 O 的位置letisBorderfalse;// 是否被围绕的标识// DFS辅助函数constdfs(row:number,col:number){constkey${row},${col};// 当前元素位置信息if(visited.has(key))return;// 避免重复访问元素// 添加位置信息visited.add(key);oset.add(key);// 边界判断触达边界则标记if(row0||rowboard.length-1||col0||colboard[0].length-1){isBordertrue;}// 上下左右递归constdirs[[-1,0],[1,0],[0,-1],[0,1]];for(const[dr,dc]ofdirs){constrrowdr;constccoldc;if(board[r]?.[c]O)dfs(r,c);}};// 主遍历for(leti0;iboard.length;i){for(letj0;jboard[0].length;j){if(board[i][j]X||visited.has(${i},${j}))continue;isBorderfalse;oset.clear();dfs(i,j);// 非边界连通区域全部改为Xif(!isBorder){oset.forEach(loc{const[r,c]loc.split(,).map(Number);board[r][c]X;});}}}}我们其实可以很容易的发现所有 ‘O’ 相连的区域只有两种情况触碰到边界 和 未触碰到边界被 ‘X’ 包围那我们完全可以先找到边界上的 ‘O’递归出他们相邻的 ‘O’并将他们修改成另外的标识比如 ‘C’最终再遍历整个 board 将 ‘C’ 设成 ‘O’, ‘O’ 设成 ‘X’ 即可。functionsolve(board:string[][]):void{// DFS辅助函数constdfs(row:number,col:number){// 将所有边界相邻的 O 标记为 Cboard[row][col]C// 上下左右递归相邻的 Oconstdirs[[-1,0],[1,0],[0,-1],[0,1]];for(const[dr,dc]ofdirs){constrrowdr;constccoldc;if(board[r]?.[c]O)dfs(r,c);}};for(leti0;iboard.length;i){// 找到左右边界上的 O 进行递归标记if(board[i][0]O)dfs(i,0)if(board[i][board[0].length-1]O)dfs(i,board[0].length-1)}for(leti0;iboard[0].length;i){// 找到上下边界上的 O 进行递归标记if(board[0][i]O)dfs(0,i)if(board[board.length-1][i]O)dfs(board.length-1,i)}// 遍历整个 board, O -- X, C -- Ofor(leti0;iboard.length;i){for(letj0;jboard[0].length;j){if(board[i][j]O)board[i][j]Xif(board[i][j]C)board[i][j]O}}}题目来源力扣LeetCode