【每天学习一点算法 2026/05/15】被围绕的区域

每天学习一点算法 2026/05/15

题目:被围绕的区域

给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' 组成,捕获 所有 被围绕的区域:

连接:一个单元格与水平或垂直方向上相邻的单元格连接。

区域:连接所有 'O' 的单元格来形成一个区域。

围绕:如果一个区域中的所有 'O' 单元格都不在棋盘的边缘,则该区域被包围。这样的区域 完全 被 'X' 单元格包围。

通过 原地 将输入矩阵中的所有 'O' 替换为 'X' 来 捕获被围绕的区域。你不需要返回任何值。

这道题的思路还是很简单的,首先遍历矩阵,遇到 'O' 时,开始递归遍历完所有相邻的 'O',如果过程没有碰到边界就将这些 'O' 替换成 'X',否则就不做操作。

typescript 复制代码
function solve(board: string[][]): void {
  const visited = new Set<string>(); // 存储访问过的位置
  const oset = new Set<string>(); // 存储当前遍历相邻 'O' 的位置
  let isBorder = false; // 是否被围绕的标识

  // DFS辅助函数
  const dfs = (row: number, col: number) => {
    const key = `${row},${col}`; // 当前元素位置信息
    if (visited.has(key)) return; // 避免重复访问元素
	// 添加位置信息
    visited.add(key); 
    oset.add(key);
    
    // 边界判断:触达边界则标记
    if (row === 0 || row === board.length - 1 || col === 0 || col === board[0].length - 1) {
      isBorder = true;
    }

    // 上下左右递归
    const dirs = [[-1,0], [1,0], [0,-1], [0,1]];
    for (const [dr, dc] of dirs) {
      const r = row + dr;
      const c = col + dc;
      if (board[r]?.[c] === 'O') dfs(r, c);
    }
  };

  // 主遍历
  for (let i = 0; i < board.length; i++) {
    for (let j = 0; j < board[0].length; j++) {
      if (board[i][j] === 'X' || visited.has(`${i},${j}`)) continue;
      
      isBorder = false;
      oset.clear();
      dfs(i, j);

      // 非边界连通区域全部改为X
      if (!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' 即可。

typescript 复制代码
function solve(board: string[][]): void {
  // DFS辅助函数
  const dfs = (row: number, col: number) => {
    // 将所有边界相邻的 'O' 标记为 'C'
    board[row][col] = 'C'
    // 上下左右递归相邻的 'O'
    const dirs = [[-1,0], [1,0], [0,-1], [0,1]];
    for (const [dr, dc] of dirs) {
      const r = row + dr;
      const c = col + dc;
      if (board[r]?.[c] === 'O') dfs(r, c);
    }
  };

  for (let i = 0; i < board.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 (let i = 0; i < board[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' --> 'O'
  for (let i = 0; i < board.length; i++) {
    for (let j = 0; j < board[0].length; j++) {
      if (board[i][j] === 'O') board[i][j] = 'X'
      if (board[i][j] === 'C') board[i][j] = 'O'
    }
  }
}

题目来源:力扣(LeetCode)

相关推荐
To_OC4 小时前
LC 15 三数之和:双指针不难,难的是把去重做对
javascript·算法·leetcode
踏月的造梦星球6 小时前
DMDPC 学习:架构、部署、运维与调优
运维·数据库·学习·架构
renhongxia17 小时前
世界模型,是“空中楼阁”还是AGI的“最后一块拼图”?
运维·服务器·数据库·人工智能·算法·agi
GHL2842710908 小时前
unreferenced formal parameter 解决办法学习
学习
zephyr059 小时前
动态规划-最长上升子序列问题
算法·动态规划
闪电悠米9 小时前
力扣hot100-56.合并区间-排序详解
数据结构·算法·leetcode·贪心算法·排序算法
fanchenxinok10 小时前
学习笔记:LabVIEW调用DLL解析S19文件教程
笔记·学习·labview·dll解析
卡提西亚10 小时前
leetcode-1438. 绝对差不超过限制的最长连续子数组
算法·leetcode·职场和发展
Java面试题总结11 小时前
LeetCode 93.复原IP地址
算法·leetcode·职场和发展·.net
芷栀夏11 小时前
Java教育平台实战复盘:课程、考试与学习行为分析系统设计
java·开发语言·学习