Leetcode130. 被围绕的区域

news2024/11/25 18:58:47

Every day a Leetcode

题目来源:130. 被围绕的区域

本题给定的矩阵中有三种元素:

  • 字母 X;
  • 被字母 X 包围的字母 O;
  • 没有被字母 X 包围的字母 O。

本题要求将所有被字母 X 包围的字母 O都变为字母 X ,但很难判断哪些 O 是被包围的,哪些 O 不是被包围的。

注意到题目解释中提到:任何边界上的 O 都不会被填充为 X。 我们可以想到,所有的不被包围的 O 都直接或间接与边界上的 O 相连。

我们可以利用这个性质判断 O 是否在边界上,具体地说:

对于每一个边界上的 O,我们以它为起点,标记所有与它直接或间接相连的字母 O;

最后我们遍历这个矩阵,对于每一个字母:

  • 如果该字母被标记过,则该字母为没有被字母 X 包围的字母 O,我们将其还原为字母 O;
  • 如果该字母没有被标记过,则该字母为被字母 X 包围的字母 O,我们将其修改为字母 X。

解法1:深度优先搜索

我们可以使用深度优先搜索实现标记操作。

在下面的代码中,我们把标记过的字母 O 修改为字母 A。

代码:

/*
 * @lc app=leetcode.cn id=130 lang=cpp
 *
 * [130] 被围绕的区域
 */

// @lc code=start
class Solution
{
public:
    // 主函数
    void solve(vector<vector<char>> &board)
    {
        if (board.empty())
            return;
        int m = board.size(), n = m ? board[0].size() : 0;
        for (int i = 0; i < m; i++)
        {
            dfs(board, i, 0);
            dfs(board, i, n - 1);
        }
        for (int j = 0; j < n; j++)
        {
            dfs(board, 0, j);
            dfs(board, m - 1, j);
        }
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
            {
                if (board[i][j] == 'A')
                    board[i][j] = 'O';
                else if (board[i][j] == 'O')
                    board[i][j] = 'X';
            }
    }
    // 辅函数
    void dfs(vector<vector<char>> &board, int x, int y)
    {
        int m = board.size(), n = m ? board[0].size() : 0;
        if (x < 0 || x >= m || y < 0 || y >= n || board[x][y] != 'O')
            return;
        board[x][y] = 'A';
        dfs(board, x + 1, y);
        dfs(board, x - 1, y);
        dfs(board, x, y + 1);
        dfs(board, x, y - 1);
    }
};
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(n×m),其中 n 和 m 分别为矩阵的行数和列数。深度优先搜索过程中,每一个点至多只会被标记一次。

空间复杂度:O(n×m),其中 n 和 m 分别为矩阵的行数和列数。主要为深度优先搜索的栈的开销。

解法2:广度优先搜索

我们可以使用广度优先搜索实现标记操作。在下面的代码中,我们把标记过的字母 O 修改为字母 A。

代码:

/*
 * @lc app=leetcode.cn id=130 lang=cpp
 *
 * [130] 被围绕的区域
 */

// @lc code=start

// DFS
//  class Solution
//  {
//  public:
//      // 主函数
//      void solve(vector<vector<char>> &board)
//      {
//          if (board.empty())
//              return;
//          int m = board.size(), n = m ? board[0].size() : 0;
//          for (int i = 0; i < m; i++)
//          {
//              dfs(board, i, 0);
//              dfs(board, i, n - 1);
//          }
//          for (int j = 0; j < n; j++)
//          {
//              dfs(board, 0, j);
//              dfs(board, m - 1, j);
//          }
//          for (int i = 0; i < m; i++)
//              for (int j = 0; j < n; j++)
//              {
//                  if (board[i][j] == 'A')
//                      board[i][j] = 'O';
//                  else if (board[i][j] == 'O')
//                      board[i][j] = 'X';
//              }
//      }
//      // 辅函数
//      void dfs(vector<vector<char>> &board, int x, int y)
//      {
//          int m = board.size(), n = m ? board[0].size() : 0;
//          if (x < 0 || x >= m || y < 0 || y >= n || board[x][y] != 'O')
//              return;
//          board[x][y] = 'A';
//          dfs(board, x + 1, y);
//          dfs(board, x - 1, y);
//          dfs(board, x, y + 1);
//          dfs(board, x, y - 1);
//      }
//  };

// BFS
class Solution
{
private:
    vector<int> direction{-1, 0, 1, 0, -1};

public:
    // 主函数
    void solve(vector<vector<char>> &board)
    {
        if (board.empty())
            return;
        int m = board.size(), n = m ? board[0].size() : 0;
        queue<pair<int, int>> q;
        // 从最外围开始,初始化队列
        for (int i = 0; i < m; i++)
        {
            if (board[i][0] == 'O')
            {
                q.push(pair<int, int>{i, 0});
                board[i][0] = 'A';
            }
            if (board[i][n - 1] == 'O')
            {
                q.push(pair<int, int>{i, n - 1});
                board[i][n - 1] = 'A';
            }
        }
        for (int j = 0; j < n; j++)
        {
            if (board[0][j] == 'O')
            {
                q.push(pair<int, int>{0, j});
                board[0][j] = 'A';
            }
            if (board[m - 1][j] == 'O')
            {
                q.push(pair<int, int>{m - 1, j});
                board[m - 1][j] = 'A';
            }
        }
        // BFS遍历
        while (!q.empty())
        {
            auto [r, c] = q.front();
            q.pop();
            for (int k = 0; k < 4; k++)
            {
                int x = r + direction[k], y = c + direction[k + 1];
                if (x < 0 || x >= m || y < 0 || y >= n || board[x][y] != 'O')
                    continue;
                q.push(pair<int, int>{x, y});
                board[x][y] = 'A';
            }
        }
        // 最终修改
        for (int i = 0; i < m; i++)
            for (int j = 0; j < n; j++)
            {
                if (board[i][j] == 'A')
                    board[i][j] = 'O';
                else if (board[i][j] == 'O')
                    board[i][j] = 'X';
            }
    }
};
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(n×m),其中 n 和 m 分别为矩阵的行数和列数。广度优先搜索过程中,每一个点至多只会被标记一次。

空间复杂度:O(n×m),其中 n 和 m 分别为矩阵的行数和列数。主要为广度优先搜索的队列的开销。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/959493.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文献阅读:Semantic Communications for Speech Signals

目录 论文简介动机&#xff1a;为什么作者想要解决这个问题&#xff1f;贡献&#xff1a;作者在这篇论文中完成了什么工作(创新点)&#xff1f;规划&#xff1a;他们如何完成工作&#xff1f;自己的看法(作者如何得到的创新思路) 论文简介 作者 Zhenzi Weng Zhijin Qin Geoffre…

网工知识角|掌握MPLS协议从这五个方面入手

今天IELAB李强伟老师(CCNA&HCIA DATACOM/ CCNP EI/ HCIP DATACOM课程讲师)给大家普及一下【MPLS协议的基本介绍】。 ​ 一、什么是MPLS VPN呢&#xff1f; MPLS VPN 是一种虚拟专用网络&#xff0c;它通过 MPLS 技术将不同位置的用户连接在一起&#xff0c;实现安全、高效…

Seata1.5.2+Nacos分布式事务环境搭建详解

文章目录 一、下载seata server二、配置application.yml三、初始Mysql数据库四、导入初始配置到nacos五、启动测试 本文以seata-server-1.5.2&#xff0c;以配置中心、注册中心使用Nacos&#xff0c;store.modedb&#xff08;mysql&#xff09;为例进行操作。 Seata简介及入门参…

掌握这个操作,数据中心才算入门!

在现代的信息技术&#xff08;IT&#xff09;领域&#xff0c;不间断电源&#xff08;UPS&#xff09;扮演着至关重要的角色&#xff0c;它们是保障数据中心、服务器以及其他关键设备持续高效运行的关键组件之一。 UPS系统的任务是在电力故障、电压波动或其他电力问题发生时&am…

如何判断自己的qt版本呢?

如何判断自己的qt版本呢? 前情提要很简单,按照如下图所示,即可查看当前打开的qtCreator的版本如何打开5.15.2版本的qtCreator呢?安装教程 前情提要 我的电脑已经安装了qt5.14.1,然后我又安装了qt5.15.2,我想尝试一下同一台电脑能否适应两个版本的qt? 当我安装完成qt5.15.2后…

短信验证码服务

使用的是 阿里云 阿里云官网 1.找到 左上角侧边栏 -云通信 -短信服务 2.在快速学习测试处 &#xff0c;按照步骤完成快速学习&#xff0c;绑定要测试的手机号&#xff0c;选专用 【测试模板】&#xff0c;自定义模板需要人工审核&#xff0c;要一个工作日 3.右上角 获取 Acces…

UDS 29 认证服务

UDS协议定义了一套标准的诊断服务&#xff0c;包括会话控制、诊断请求、诊断响应和ECU编程等功能。通过UDS协议&#xff0c;诊断工具可以向ECU发送特定的请求&#xff0c;获取ECU的状态信息和故障码&#xff0c;诊断和解决故障问题。UDS是ISO 14229标准定义的一种通信协议&…

python错误:AttributeError: module ‘pydot‘ has no attribute ‘find_graphviz‘

1.安装pydot-ng 由于pydot里面已经没有这个find_graphviz()方法了&#xff0c;选择安装pydot-ng activate python虚拟环境 pip install pydot-ng2安装graphviz 到graphviz官网上下载exe并点击安装&#xff0c;勾选添加到全局变量。 或者记住安装位置选择手动添加到path变…

Javascript动态添加表格行

1.Javascript如何动态添加表格行 图一 图二 1.首先要找到添加按钮代码&#xff0c;设置id选择器 <button type"button" id"insertRow" class"btn btn-danger" style"background-color: #ca6307;border: none">新增一项&l…

【VTK】 vtkMapper

很高兴在雪易的CSDN遇见你 ,给你糖糖 欢迎大家加入雪易社区-CSDN社区云 前言 本文主要分享VTK中关于vtkMapper的相关知识和使用方法,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO </

工时管理:如何创建和管理工时表

工时管理是人力资源和业务管理的重要组成部分&#xff0c;对于项目管理也是不可或缺的。无论是哪种类型的工作&#xff0c;如果有团队或员工&#xff0c;那么你就需要工时表来跟踪时间和费用。 什么是工时表&#xff1f; 工时表是一种物理或电子文档&#xff0c;雇主用它来跟…

OCR多语言识别模型构建资料收集

OCR多语言识别模型构建 构建多语言识别模型方案 合合&#xff0c;百度&#xff0c;腾讯&#xff0c;阿里这四家的不错 调研多家&#xff0c;发现有两种方案&#xff0c;但是大多数厂商都是将多语言放在一个字典里&#xff0c;构建1w~2W的字典&#xff0c;训练一个可识别多种语…

【监控平台 - zabbix】

目录 一、环境搭建 1. zabbix程序结构 2. zabbix-agent支持的协议 3. zabbix监控环境搭建 3.1 安装方式 3.2 配置zabbix官方yum源 3.3 安装服务端与客户端 3.4 安装zabbix-web 3.4.1 cd /etc/yum.repos.d/ 3.4.2 安装依赖源 3.4.3 安装本部件 3.4.4 安装存储数据库…

时序预测 | Matlab实现CNN-XGBoost卷积神经网络结合极限梯度提升树时间序列预测

时序预测 | Matlab实现CNN-XGBoost卷积神经网络结合极限梯度提升树时间序列预测 目录 时序预测 | Matlab实现CNN-XGBoost卷积神经网络结合极限梯度提升树时间序列预测效果一览基本描述程序设计参考资料 效果一览 基本描述 时序预测 | Matlab实现CNN-XGBoost卷积神经网络结合极限…

Effective STL 1.仔细选择你的容器

Effective STL 1.仔细选择你的容器 文章目录 Effective STL 1.仔细选择你的容器迭代器容器分类连续内存容器和基于节点的容器的区别 如何选择容器结语>>>>> 欢迎关注公众号【三戒纪元】 <<<<< 标准序列容器 vector、string、deque 和 list 标准…

【技巧】如何在Excel表格中添加水印?

想要在Excel表格中添加水印展示&#xff0c;但是Excel并没有像word文档一样的直接添加水印的功能&#xff0c;怎么办&#xff1f; 今天小编来分享一个方法&#xff0c;也能实现Excel表格的添加水印~ 1、 打开Excel表格&#xff0c;依次点击菜单栏的“插入” → “文本框” →…

小件固定资产怎么管理好

对于小件固定资产的管理&#xff0c;可以考虑以下几个方面&#xff1a;  建立资产档案&#xff1a;对所有小件固定资产进行登记、编号、分类、评估等工作&#xff0c;建立详细的资产档案。  定期盘点&#xff1a;定期对小件固定资产进行盘点&#xff0c;确保资产账面与实际…

【2022】贝壳找房秋招C++工程师笔试卷1 牛妹的字符串

牛妹的字符串 牛妹拿到了一个只由小写字母组成的字符串s&#xff0c;接下来将字符串执行k次操作&#xff0c;每次操作都会把s中ASCII码最小的字母从s中删除&#xff0c;请返回k次操作之后的字符串s。 参考优秀的网友1&#xff1a;26个小写字母 放在数组里正好由大到小排序。 …

聚合多个电商API接口平台

API接口测试&#xff08;点击免费测试&#xff09; 随着数字化商业时代的到来&#xff0c;API接口已成为电商资源连接利器&#xff0c;也是全球传统互联网企业转型的基础。 2021年 Google Cloud 研究显示&#xff0c;全球互联网企业近3/4的企业持续投入数字化转型&#xff0c…

SpingBoot 过滤器和拦截器有什么区别?

1. 运行顺序不同&#xff08;如图&#xff09;&#xff1a; 过滤器是在 Servlet 容器接收到请求之后&#xff0c;但在 Servlet 被调用之前运行的&#xff1b;而拦截器则是在 Servlet 被调用之后&#xff0c;但在响应被发送到客户 端之前运行的。 2. 配置方式不同&#xff1a; …