当前位置: 面试刷题>> 被围绕的区域(经典算法150题)


### 题目描述 给定一个二维的0和1的矩阵(`grid`),其中0表示空地,1表示建筑物。一个建筑物如果所有四个方向(上、下、左、右)的相邻格子都是空地(0)或超出了矩阵的边界,那么这个建筑物就是“被围绕的”。请编写一个算法,输出一个与原始矩阵相同大小的矩阵,但是其中所有被围绕的建筑物(即值为1的格子)被翻转为0,而所有其他格子保持不变。 ### 示例 输入: ``` grid = [ [1,1,1],[ [1,0,1], [1,1,1] ] ``` 输出: ``` [ [1,0,1], [1,0,1], [1,0,1] ] ``` 解释:所有的建筑物都被围绕了,因此它们都被翻转成了0。 ### PHP 示例代码 ```php function solve($grid) { if (empty($grid) || empty($grid[0])) return $grid; $rows = count($grid); $cols = count($grid[0]); // 从边界开始,将所有与边界相连的1标记为2(视为非被围绕) for ($i = 0; $i < $rows; $i++) { if ($grid[$i][0] == 1) dfs($grid, $i, 0); if ($grid[$i][$cols - 1] == 1) dfs($grid, $i, $cols - 1); } for ($j = 0; $j < $cols; $j++) { if ($grid[0][$j] == 1) dfs($grid, 0, $j); if ($grid[$rows - 1][$j] == 1) dfs($grid, $rows - 1, $j); } // 将剩余的1(即被围绕的)翻转为0,将2(非被围绕的)翻转回1 for ($i = 0; $i < $rows; $i++) { for ($j = 0; $j < $cols; $j++) { if ($grid[$i][$j] == 2) { $grid[$i][$j] = 1; } elseif ($grid[$i][$j] == 1) { $grid[$i][$j] = 0; } } } return $grid; } function dfs(&$grid, $row, $col) { $rows = count($grid); $cols = count($grid[0]); if ($row < 0 || $row >= $rows || $col < 0 || $col >= $cols || $grid[$row][$col] != 1) { return; } $grid[$row][$col] = 2; dfs($grid, $row - 1, $col); dfs($grid, $row + 1, $col); dfs($grid, $row, $col - 1); dfs($grid, $row, $col + 1); } // 示例用法 $grid = [ [1, 1, 1], [1, 0, 1], [1, 1, 1] ]; $result = solve($grid); print_r($result); ``` ### Python 示例代码 ```python def solve(grid): if not grid or not grid[0]: return grid rows, cols = len(grid), len(grid[0]) def dfs(r, c): if r < 0 or r >= rows or c < 0 or c >= cols or grid[r][c] != 1: return grid[r][c] = 2 dfs(r - 1, c) dfs(r + 1, c) dfs(r, c - 1) dfs(r, c + 1) # 标记与边界相连的1为2 for i in range(rows): if grid[i][0] == 1: dfs(i, 0) if grid[i][cols - 1] == 1: dfs(i, cols - 1) for j in range(cols): if grid[0][j] == 1: dfs(0, j) if grid[rows - 1][j] == 1: dfs(rows - 1, j) # 将剩余的1翻转为0,2翻转回1 for i in range(rows): for j in range(cols): if grid[i][j] == 2: grid[i][j] = 1 elif grid[i][j] == 1: grid[i][j] = 0 return grid # 示例用法 grid = [ [1, 1, 1], [1, 0, 1], [1, 1, 1] ] result = solve(grid) print(result) ``` ### JavaScript 示例代码 ```javascript function solve(grid) { if (!grid.length || !grid[0].length) return grid; const rows = grid.length; const cols = grid[0].length; function dfs(r, c) { if (r < 0 || r >= rows || c < 0 || c >= cols || grid[r][c] !== 1) return; grid[r][c] = 2; dfs(r - 1, c); dfs(r + 1, c); dfs(r, c - 1); dfs(r, c + 1); } // 标记与边界相连的1为2 for (let i = 0; i < rows; i++) { if (grid[i][0] === 1) dfs(i, 0); if (grid[i][cols - 1] === 1) dfs(i, cols - 1); } for (let j = 0; j < cols; j++) { if (grid[0][j] === 1) dfs(0, j); if (grid[rows - 1][j] === 1) dfs(rows - 1, j); } // 将剩余的1翻转为0,2翻转回1 for (let i = 0; i < rows; i++) { for (let j = 0; j < cols; j++) { if (grid[i][j] === 2) grid[i][j] = 1; else if (grid[i][j] === 1) grid[i][j] = 0; } } return grid; } // 示例用法 const grid = [ [1, 1, 1], [1, 0, 1], [1, 1, 1] ]; const result = solve(grid); console.log(result); ``` 这些示例代码均展示了如何使用深度优先搜索(DFS)来找到并标记与边界相连的建筑物,然后将剩余的建筑物(即被围绕的)翻转为0。
推荐面试题