Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
130. 被围绕的区域
给你一个 m x n
的矩阵 board
,由若干字符 'X'
和 'O'
,找到所有被 'X'
围绕的区域,并将这些区域里所有的 'O'
用 'X'
填充。
示例 1:
输入: board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
输出: [["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
解释: 被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
二、思路分析:
一看到这样的矩阵一下就想到了深度搜索和广度搜索,两者是差不多的,那我们就用深搜索试一下这题,首先题目说了要包围着的“O”才不保留,也就是说只有矩阵周围的“O”和与之连接在一起的“O”会被保留起来,那么我们只需要对矩阵的四个边界进行遍历,然后对值是“O”的进行深搜,把遍历到的所有“O”,都保留起来就可以了,那么我们怎么保留呢?这里就要用一点点及技巧了,一开始我是想着用一个拷贝数组来保留这个数组,然后原数组,然后再对拷贝数组进行刚才深搜的操作,看似没有什么问题,但是一跑就栈溢出了,仔细一想原来是如果全地图都是“O”的话,那么从A搜到B再从B搜到A就会陷入死递归,那么只能换个办法了。后来发现是自己想复杂了,其实我们只要在边界深搜的时候,把遍历到的“O”,变成其他的任意字符(除了O和X)就可以了,这里我用了"-",然后边界搜索完成后,我们只要把整个矩阵进行一次遍历,把值为“-”的变成“O”,其他的全部变成“X”,那么这道题目就解决了。
- 定义一个方向数组,为了美观,当然也可以没有。
- 对矩阵边界进行深搜,注意这里的边界的四个角落不要重复了!!!。
- 深搜函数的书写,如果新的下标没有超过边界且为“O”,那么久继续递归下去。
- 遍历整个矩阵,查看是“-”的地方置为“O”,其他的置之为“X”。
- 完美。
三、AC 代码:
代码一:
/**
* @param {character[][]} board
* @return {void} Do not return anything, modify board in-place instead.
*/
var solve = function(board) {
let m=board.length,n=board[0].length;
let direction=[[0,1],[0,-1],[1,0],[-1,0]];
for(let i=0;i<m;i++){
if(board[i][0]==='O'){
dfs(i,0);
}
if(board[i][n-1]==='O'){
dfs(i,n-1);
}
}
for(let j=1;j<n-1;j++){
if(board[0][j]==='O'){
dfs(0,j);
}
if(board[m-1][j]==='O'){
dfs(m-1,j);
}
}
for(let i=0;i<m;i++){
for(let j=0;j<n;j++){
if(board[i][j]==='-'){
board[i][j]='O';
}else{
board[i][j]='X';
}
}
}
function dfs(x,y){
board[x][y]='-';
for(let i=0;i<4;i++){
let curX=x+direction[i][0],curY=y+direction[i][1];
if(curX<m&&curX>=0&&curY>=0&&curY<n&&board[curX][curY]==='O'){
dfs(curX,curY);
}
}
}
};
四、总结:
对于这种矩阵的覆盖问题很适合深搜和广搜,多注意边界细节!