【每天学习一点算法 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)

相关推荐
知识分享小能手7 分钟前
C++ 学习教程,从入门到精通,C++ 入门知识 — 完整知识点(1)
开发语言·c++·学习
INGNIGHT1 小时前
270 · 电话号码的字母组合II(Trie)
linux·算法
2401_839080541 小时前
C++常见八股
数据结构·c++·算法
青山是哪个青山2 小时前
LeetCode 188:买卖股票的最佳时机 IV
算法
mikuyyds2 小时前
geo-toolbox 插件算法解析:RUSLE 与 MUSLE 的工程化落地
算法·rust·gis
a187927218312 小时前
【算法】树(二):队列与祖先——BFS 骨架三配件、短路透传与合流
算法·leetcode·二叉树··bfs·算法讲解·树遍历
syagain_zsx3 小时前
算法基础篇 · 03 枚举(C++ 题解)
c++·算法·二进制·枚举
weixin_307779133 小时前
C++代码实现MATLAB中的ode23tb函数功能
开发语言·c++·算法·matlab
AI职业加油站3 小时前
数据要素价值释放年:大数据治理工程师,站上职业新风口
人工智能·学习·职场和发展·数据分析·职场发展
啄缘之间3 小时前
1.【SVA】什么是SVA?
经验分享·学习·测试用例·verilog·sva