力扣130题:被围绕的区域DFS/BFS解法与优化
1. 问题背景与核心挑战今天咱们来啃一块硬骨头——力扣第130题被围绕的区域。这道题在面试中的出现频率相当高尤其喜欢考那些自诩精通DFS/BFS的候选人。题目看似简单给定一个二维矩阵把所有被X完全包围的O区域替换为X。但实际操作中90%的候选人都会掉进同一个坑里。我第一次遇到这个问题是在某大厂终面当时自信满满地写了个标准DFS结果面试官微微一笑如果棋盘是1000×1000呢瞬间栈溢出。这道题的精妙之处在于它考察的不仅是基础算法能力更是对问题本质的理解和优化思维。2. 暴力DFS解法与致命缺陷2.1 最直观的暴力思路大多数人包括当年的我的第一反应是这样的遍历整个矩阵遇到O就启动DFS/BFS检查这个区域是否被X完全包围如果是就全部翻转为X用Python实现的伪代码大概长这样def solve(board): if not board: return m, n len(board), len(board[0]) def dfs(i, j): if 0 i m and 0 j n and board[i][j] O: board[i][j] # dfs(i1, j) dfs(i-1, j) dfs(i, j1) dfs(i, j-1) for i in range(m): for j in range(n): if board[i][j] O: # 临时标记为#以便后续处理 dfs(i, j) # 检查是否被包围需要额外实现check_surrounded函数 if check_surrounded(board, i, j): flip_region(board, #, X) else: flip_region(board, #, O)2.2 这个解法为什么不行这个解法有三个致命问题栈溢出风险当矩阵很大时比如1000×1000全是O递归深度会达到百万级直接爆栈重复计算同一个O可能被多个相邻O重复访问逻辑漏洞边缘的O区域永远不会被包围但上述代码仍会尝试处理关键教训在矩阵类问题中递归实现的DFS往往不是最优解特别是在面对大规模数据时。面试官设置这样的边界条件就是为了考察候选人是否考虑到了算法在实际工程中的应用场景。3. 逆向思维从边缘突围3.1 解题思路的重构经过前面的失败我们需要换个角度思考与其费力寻找被包围的区域不如直接找出没有被包围的区域——也就是所有与边缘相连的O区域。剩下的O自然就是被包围的。具体步骤先处理四条边上的O用DFS/BFS标记所有与之相连的O这些被标记的O就是存活区域不应该被翻转最后遍历整个矩阵未被标记的O→翻转为X被标记的O→恢复为O3.2 优化后的代码实现def solve(board): if not board: return m, n len(board), len(board[0]) def dfs(i, j): if 0 i m and 0 j n and board[i][j] O: board[i][j] S # S表示Survive dfs(i1, j) dfs(i-1, j) dfs(i, j1) dfs(i, j-1) # 处理第一列和最后一列 for i in range(m): if board[i][0] O: dfs(i, 0) if board[i][n-1] O: dfs(i, n-1) # 处理第一行和最后一行 for j in range(n): if board[0][j] O: dfs(0, j) if board[m-1][j] O: dfs(m-1, j) # 最终处理 for i in range(m): for j in range(n): if board[i][j] O: board[i][j] X elif board[i][j] S: board[i][j] O4. 工程优化用迭代代替递归4.1 避免栈溢出的BFS实现虽然上面的解法已经不错但在极端情况下仍可能栈溢出。更工程化的做法是用显式栈DFS或队列BFS代替递归。以下是BFS实现from collections import deque def solve(board): if not board: return m, n len(board), len(board[0]) queue deque() # 将边缘的O加入队列 for i in range(m): if board[i][0] O: queue.append((i, 0)) if board[i][n-1] O: queue.append((i, n-1)) for j in range(n): if board[0][j] O: queue.append((0, j)) if board[m-1][j] O: queue.append((m-1, j)) # BFS标记所有连通区域 while queue: i, j queue.popleft() if 0 i m and 0 j n and board[i][j] O: board[i][j] S queue.append((i1, j)) queue.append((i-1, j)) queue.append((i, j1)) queue.append((i, j-1)) # 最终处理 for i in range(m): for j in range(n): if board[i][j] O: board[i][j] X elif board[i][j] S: board[i][j] O4.2 复杂度分析时间复杂度O(M×N)每个节点最多被访问两次标记和最终处理空间复杂度O(M×N)最坏情况下需要存储所有边缘节点5. 面试中的进阶考察点5.1 如何应对面试官的追问在实际面试中面试官可能会提出以下进阶问题如果矩阵太大无法放入内存怎么办答可以分块处理但需要额外记录边缘信息如何并行化这个算法答可以按行/列分片但需要处理边界处的O区域合并如果O和X的含义反转找被O包围的X会怎样答算法逻辑完全对称只需调整标记条件5.2 实际工程中的应用变种这类区域填充算法在实际工程中有很多应用场景图像处理中的连通区域分析地图服务中的封闭区域检测游戏开发中的地形生成电路设计中的短路检测6. 代码模板与记忆技巧6.1 通用DFS/BFS模板对于矩阵类的DFS/BFS问题可以记住这个通用模板def matrix_dfs_bfs(matrix): if not matrix: return m, n len(matrix), len(matrix[0]) directions [(1,0), (-1,0), (0,1), (0,-1)] # 四连通方向 # DFS递归实现 def dfs(i, j): # 边界检查 if not (0 i m and 0 j n): return # 业务逻辑判断 if matrix[i][j] ! target_condition: return # 处理当前节点 process_current(matrix, i, j) # 递归邻居 for di, dj in directions: dfs(idi, jdj) # BFS队列实现 from collections import deque queue deque(initial_nodes) while queue: i, j queue.popleft() # 边界检查 if not (0 i m and 0 j n): continue # 业务逻辑判断 if matrix[i][j] ! target_condition: continue # 处理当前节点 process_current(matrix, i, j) # 加入邻居 for di, dj in directions: queue.append((idi, jdj))6.2 解题思路记忆口诀对于这类区域填充问题可以记住这个口诀 边缘入手标记活中间剩余全消灭解释先从边缘找到所有存活点与边缘连通的O标记这些存活点如改为S最后遍历整个矩阵未被标记的O→消灭改为X被标记的S→恢复改回O7. 同类问题举一反三掌握这个思路后可以轻松解决以下类似问题力扣200. 岛屿数量力扣695. 岛屿的最大面积力扣463. 岛屿的周长力扣529. 扫雷游戏力扣994. 腐烂的橘子这些问题的共同特点是都需要在矩阵中找到符合条件的连通区域只是处理逻辑稍有不同。建议按这个顺序练习逐步掌握变种问题的解法。

相关新闻

华硕笔记本终极性能优化指南:G-Helper完整配置教程

华硕笔记本终极性能优化指南:G-Helper完整配置教程

华硕笔记本终极性能优化指南:G-Helper完整配置教程 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, Exper…

2026/10/1 20:28:15 阅读更多 →
小米智能摄像机4 Max AI变焦版:家用安防如何实现清晰远距离监控

小米智能摄像机4 Max AI变焦版:家用安防如何实现清晰远距离监控

1. 先搞清楚 739 元能买到什么样的 AI 变焦摄像机如果你正在看家用智能摄像机,特别是想找一个能看清远处细节的,那小米新出的这个“4 Max AI 变焦版”就值得关注。它最核心的能力,不是简单的“能放大”,而是通过 AI 算法和物理变焦…

2026/10/2 21:56:12 阅读更多 →
边端AI技术解析:从模型轻量化到工业质检实战部署

边端AI技术解析:从模型轻量化到工业质检实战部署

1. 项目概述:当AI从云端“下放”到边缘最近和几个做物联网和嵌入式开发的老朋友聊天,话题总绕不开“边端AI”。大家普遍的感觉是,这玩意儿火得有点不讲道理,但仔细一想,又觉得理所当然。表面上看,大家讨论的…

2026/10/1 21:09:45 阅读更多 →

最新新闻

基于YOLOv8的徽章分析系统:从训练到部署的完整毕设实战

基于YOLOv8的徽章分析系统:从训练到部署的完整毕设实战

简介:这是一套面向计算机、人工智能、通信工程等专业学生与教师的YOLOv8徽章分析系统完整项目包,可直接用于毕业设计、课程设计或大作业,也适合深度学习入门者进阶练习。资源包含源码、完整数据集、可视化界面与部署说明,部署简单…

2026/10/2 22:01:08 阅读更多 →
Java学籍管理系统源码解析:从数据库设计到答辩避坑

Java学籍管理系统源码解析:从数据库设计到答辩避坑

简介:面向软件工程本科期末大作业的Java学籍管理系统完整源码包,按学院学籍管理要求梳理学生基本信息、班级信息、专业信息、动态信息等模块,兼顾考勤、纪律、寝室、卫生等日常管理场景,适合高校学生用于课程设计、期末项目或毕业…

2026/10/2 22:01:08 阅读更多 →
发电厂指针仪表数据集:XML标注与YOLO训练全流程

发电厂指针仪表数据集:XML标注与YOLO训练全流程

简介:这份资源是面向电力行业智能化改造与计算机视觉学习者的发电厂指针仪表数据集,适用于目标检测模型训练、仪表自动读数研究及工业监控系统开发等场景。包内共2000个文件,以1214个xml标注文件和785张jpg仪表图像为主,另含1个说…

2026/10/2 22:01:07 阅读更多 →
Python电商销售数据分析:从数据清洗到可视化全流程

Python电商销售数据分析:从数据清洗到可视化全流程

最近在折腾一个电商销售数据项目,用Python把几十万条订单记录拆了个底朝天。这个项目不算复杂,但却是数据分析里最典型、最能练手的一条完整链路:从原始订单表出发,经过数据清洗、指标加工、分组聚合到可视化输出,最后…

2026/10/2 22:01:06 阅读更多 →
手写数学运算识别系统:Python+CNN完整实现与避坑指南

手写数学运算识别系统:Python+CNN完整实现与避坑指南

简介:一套基于Python的手写数学运算识别系统源码,面向计算机视觉与机器学习方向的毕业设计及课程实践。系统完整覆盖图像灰度化与二值化、特征提取、分类器训练、表达式解析与结果输出等环节,适合需要快速搭建识别项目或理解工程化流程的开发…

2026/10/2 22:01:06 阅读更多 →
MapReduce核心原理与实训实战:从排序到数据清洗

MapReduce核心原理与实训实战:从排序到数据清洗

如果让我用一句话概括MapReduce,我会说它是大数据时代“先分后合”思想最经典的落地产物。你只需要写好一份Map函数和一份Reduce函数,剩下的切分、调度、容错、排序,框架全替你扛住。过去十年里,几乎每一门大数据课程、每一个实训…

2026/10/2 22:00:05 阅读更多 →

日新闻

从零搭建AI工程化:模型之外的完整闭环

从零搭建AI工程化:模型之外的完整闭环

先搞清楚一件事:从零开始做 AI 工程化,难的从来不是调模型、写提示词,而是把一套原型 Demo 变成长得像是“正经系统”的东西。你手里可能已经有了能跑通的代码,也可能刚读完一些概念,但真到了要把它变成可维护、可观测…

2026/10/2 0:00:20 阅读更多 →
大模型训练显存估计与混合精度训练实战指南

大模型训练显存估计与混合精度训练实战指南

1. 大模型训练显存估计与混合精度训练详解显存不够用,几乎是每个做大模型训练的人都会撞上的第一堵墙。你可能也经历过:模型代码写完了,数据管道跑通了,满心欢喜地按下训练启动脚本,结果几秒钟后终端弹出一行红字——C…

2026/10/2 0:00:20 阅读更多 →
小样本学习数据集选型指南:27个真正可用的高质量数据集

小样本学习数据集选型指南:27个真正可用的高质量数据集

1. 小样本学习的“弹药库”:为什么你总在找数据集,却总找不到真正能用的? 小样本、数据集——这两个词最近半年在我处理的200多个AI项目咨询里,出现频率排进前三。不是模型调不好,不是代码写不对,而是卡在…

2026/10/2 0:00:20 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/1 19:40:48 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/1 19:41:40 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/1 20:05:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 5:26:06 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 6:09:11 阅读更多 →