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

相关推荐
芜湖xin1 小时前
【题解-洛谷】P1012 [NOIP 1998 提高组] 拼数
算法·贪心
秋雨梧桐叶落莳1 小时前
iOS——ZARA仿写项目
学习·macos·ios·objective-c·cocoa
KKei16381 小时前
Flutter for OpenHarmony 学习视频播放器技术文章
学习·flutter·华为·音视频·harmonyos
xiaoxiaoxiaolll2 小时前
金属结构疲劳寿命预测与健康监测技术
人工智能·算法·机器学习
故事和你912 小时前
洛谷-【图论2-1】树4
开发语言·数据结构·c++·算法·动态规划·图论
故事和你912 小时前
洛谷-【图论2-1】树1
开发语言·数据结构·c++·算法·深度优先·动态规划·图论
敲代码的嘎仔2 小时前
力扣高频SQL基础50题详解
开发语言·数据库·笔记·sql·算法·leetcode·后端开发
小虎牙0072 小时前
面试被问复杂度总懵?这篇指南帮你彻底搞清
算法
weixin_428005303 小时前
C#调用 AI学习从0开始-第1阶段(基础与工具)-第2天Prompt工程基础
人工智能·学习·c#·prompt