算法笔记(十二)——BFS 解决 FloodFill(洪水灌溉)

news2024/11/27 4:25:38

文章目录

  • 图像渲染
  • 岛屿数量
  • 岛屿的最大面积
  • 被围绕的区域

FloodFill(洪水灌溉)

颜色填充
想Windows画图板中的油漆点一下可以把一个联通的块儿全部染色

本质就是找一块区域里性质相同的联通块


图像渲染

题目:图像渲染

在这里插入图片描述
思路

BFS一层一层搜索,等于修改的

C++代码

class Solution 
{
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0}; 
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) 
    {
        int oldColor = image[sr][sc]; // 先标记需要修改的像素值
        if(oldColor == color) return image;

        queue<pair<int, int>> q;
        q.push({sr, sc});

        int m = image.size(), n = image[0].size();
        while(q.size())
        {
            auto [a, b] = q.front();
            q.pop();
            image[a][b] = color; // 修改当前位置的颜色

            for (int i = 0; i < 4; i++) 
            {
                int x = a + dx[i];
                int y = b + dy[i];
                
                // 判断新的坐标是否越界,并且颜色与旧颜色相同
                if (x >= 0 && x < m && y >= 0 && y < n && image[x][y] == oldColor) 
                {
                    q.push({x, y});
                }
            }
        }

        return image;
    }
};

岛屿数量

题目:岛屿数量

在这里插入图片描述
思路

  1. 初始化
  • 创建一个二维布尔数组 visited 来跟踪哪些单元格已经被访问过
  • 初始化岛屿计数器 ret = 0
  1. 使用两个嵌套的循环遍历网格中的每个单元格
  2. 对于每个单元格,检查它是否是陆地1且尚未被访问过,如果满足条件,说明我们找到了一个新的岛屿
  3. BFS 从当前陆地单元格开始搜索整个岛屿,使用队列来迭代地访问它们,在搜索过程中,将访问过的单元格标记为已访问,即在visited 数组中设置为 true
  4. 每次成功搜索完一个岛屿后,将岛屿计数器 ret++

C++代码

class Solution 
{  
    // 方向数组  
    vector<int> dx = {0, 0, 1, -1};  
    vector<int> dy = {1, -1, 0, 0};  
    vector<vector<bool>> visited;  
    int m, n; // m 表示行数,n 表示列数  
    int ret; // 岛屿数量  
    queue<pair<int, int>> q;  
  
    void bfs(const vector<vector<char>>& grid, int i, int j) 
    {  
        q.push({i, j}); // 起点入队  
        visited[i][j] = true; // 标记已经遍历  
  
        while (!q.empty()) 
        {  
            auto [a, b] = q.front();  
            q.pop();  
            for (int k = 0; k < 4; ++k)
             { // 注意这里应该是 ++k 而不是 i++  
                int x = a + dx[k];  
                int y = b + dy[k];  

                // 判断新的坐标是否越界,并且是岛屿的一部分  
                if (0 <= x && x < m && 0 <= y && y < n && grid[x][y] == '1' && !visited[x][y]) 
                {  
                    q.push({x, y});  
                    visited[x][y] = true;  
                }  
            }  
        }  
    }  
  
public:  
    int numIslands(vector<vector<char>>& grid) 
    {  
        m = grid.size();  
        n = grid[0].size();  

        visited.resize(m, vector<bool>(n, false)); // 初始化 visited 数组  
        ret = 0; // 初始化岛屿数量  
  
        for (int i = 0; i < m; ++i) 
        {  
            for (int j = 0; j < n; ++j) 
            {  
                if (grid[i][j] == '1' && !visited[i][j]) 
                {  
                    ret++; // 发现新的岛屿,岛屿数量加一  
                    bfs(grid, i, j); // 遍历、标记属于同一岛屿的位置  
                }  
            }  
        }  
  
        return ret;  
    }  
};

岛屿的最大面积

题目:岛屿的最大面积

在这里插入图片描述

思路

  • 初始化最大岛屿面积为0,以及获取网格的行数和列数
  • 遍历网格中的每一个格子,如果当前格子是陆地1,则调用bfs 函数进行广度优先搜索,并更新最大岛屿面积

C++代码

class Solution 
{
    // 方向数组  
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {-1, 1, 0, 0};
    queue<pair<int, int>> q; 
    int m, n; // m 表示行数,n 表示列数  

    // BFS 函数,从起点 (i, j) 开始遍历并标记属于同一岛屿的所有位置
    int bfs(vector<vector<int>>& grid, int i, int j) 
    {
        int count = 1; // 记录岛屿的大小
        q.push({i, j}); // 将起点入队
        grid[i][j] = 0; // 标记已经遍历过的位置

        while (q.size()) 
        {
            auto [a, b] = q.front();
            q.pop();

            for (int k = 0; k < 4; ++k) 
            {
                int x = a + dx[k], y = b + dy[k];
                // 判断新的坐标是否越界,并且是岛屿的一部分
                if (0 <= x && x < m && 0 <= y && y < n && grid[x][y] == 1) 
                {
                    grid[x][y] = 0;  // 标记已经遍历过的位置
                    count++;  // 增加岛屿的大小
                    q.push({x, y});  // 将相邻的岛屿位置入队
                }
            }
        }

        return count;
    }

public:
    int maxAreaOfIsland(vector<vector<int>>& grid) 
    {
        int ret = 0;  // 记录最大岛屿面积
        m = grid.size();  // 获取行数
        n = grid[0].size();  // 获取列数

        // 遍历整个网格
        for (int i = 0; i < m; ++i) 
        {
            for (int j = 0; j < n; ++j) 
            {
                if (grid[i][j] == 1) 
                {
                    ret = max(ret, bfs(grid, i, j));  // 更新最大岛屿面积
                }
            }
        }

        return ret;  
    }
};

被围绕的区域

题目:被围绕的区域

在这里插入图片描述

思路

  • 从矩阵的边界开始,遍历所有边界上的元素
  • 如果边界上的元素是O,则使用BFS遍历所有与该O相连的元素,并将它们标记为已访问(替换为S
  • 在完成边界上的所有O的遍历后,矩阵中剩余的O即为被围绕的区域
  • 最后,将剩余的O替换为X,并将之前标记为已访问的字符(如S)还原为O

C++代码

class Solution 
{
    const int dx[4] = {0, 0, 1, -1};  
    const int dy[4] = {-1, 1, 0, 0};
    int m, n;  // m 表示行数,n 表示列数
    queue<pair<int, int>> q; 

    // BFS 函数,从起点 (i, j) 开始遍历并标记属于同一区域的所有位置
    void bfs(vector<vector<char>>& board, int i, int j) 
    {
        q.push({i, j});  // 将起点入队
        board[i][j] = 'S';  // 标记已经遍历过的位置

        while (q.size()) 
        {
            auto [a, b] = q.front();
            q.pop();

            for (int k = 0; k < 4; ++k) 
            {
                int x = a + dx[k], y = b + dy[k];
                // 判断新的坐标是否越界,并且是未被围绕的区域
                if (0 <= x && x < m && 0 <= y && y < n && board[x][y] == 'O') 
                {
                    board[x][y] = 'S';  // 标记已经遍历过的位置
                    q.push({x, y});  // 将相邻的未被围绕的区域位置入队
                }
            }
        }
    }

public:
    void solve(vector<vector<char>>& board) 
    {
        m = board.size(); 
        n = board[0].size();  

        // 对边界上的'O'进行BFS遍历,标记为'S'
        for (int i = 0; i < n; ++i) 
        {
            if (board[0][i] == 'O') bfs(board, 0, i);
            if (board[m - 1][i] == 'O') bfs(board, m - 1, i);
        }
        for (int i = 1; i < m - 1; ++i) 
        {
            if (board[i][0] == 'O') bfs(board, i, 0);
            if (board[i][n - 1] == 'O') bfs(board, i, n - 1);
        }

        // 遍历整个网格,将未被标记的'O'修改为'X',已经标记的'S'修改回'O'
        for (int i = 0; i < m; i++) 
        {
            for (int j = 0; j < n; j++) 
            {
                if (board[i][j] == 'S') board[i][j] = 'O';
                else if (board[i][j] == 'O') board[i][j] = 'X';
            }
        }
    }
};

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

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

相关文章

4.资源《Arduino UNO R3 proteus 电机PID参数整定工程文件(含驱动代码)》说明。

资源链接&#xff1a; Arduino UNO R3 proteus 电机PID参数整定工程文件&#xff08;含驱动代码&#xff09; 1.文件明细&#xff1a; 2.文件内容说明 包含&#xff1a;proteus工程&#xff0c;内含设计图和工程代码。 3.内容展示 4.简述 工程功能可以看这个视频 PID仿真调…

通过 Groovy 实现业务逻辑的动态变更

Groovy 1、需求的提出2、为什么是Groovy3、设计参考1_引入Maven依赖2_GroovyEngineUtils工具类3_GroovyScriptVar类4_脚本规则表设计5_对应的实体类6_数据库访问层7_GroovyExecService通用接口 4、测试5、其他的注意事项6、总结 1、需求的提出 在我们日常的开发过程中&#xf…

一、图解C#教程

一、堆和栈 程序运行时&#xff0c;数据存储在内存中。 使用堆和栈来存储数据 1、栈 栈是一个内存数组&#xff0c;先进后出原则。 可以存储&#xff1a;某些类型变量的值&#xff1b;程序当前执行环境&#xff1b;传递给方法的参数&#xff1b; 入栈&#xff1a;把数据放…

【超级详细解释】力扣每日一题 134.加油站 48. 旋转图像

134.加油站 力扣 这是一个很好的问题。这个思路其实基于一种贪心策略。我们从整个路径的油量变化来理解它&#xff0c;结合一个直观的“最低点法则”&#xff0c;来确保找到正确的起点。 问题的核心&#xff1a;油量差值的累积 对于每个加油站&#xff0c;我们有两个数组&…

精选算法入门——day2

精选算法入门——day2 题目一题干解题思路一解题思路二解题思路三思路三代码 题目二题干解题思路代码 题目三题干解题思路一代码解题思路二代码解题思路三代码 题目四题干解题思路代码 题目一 题干 数组中有一个数字出现的次数超过数组长度的一半&#xff0c;请找出这个数字。…

提高顾客满意度,餐饮业如何开展客户调研?

餐饮行业需明确调研目的&#xff0c;选择合适工具&#xff0c;设计问卷&#xff0c;收集并分析数据&#xff0c;持续追踪优化。通过客户调研&#xff0c;提升服务质量、顾客满意度和竞争力&#xff0c;利用ZohoSurvey等工具实现高效调研。 一、明确调研目的 进行客户调研前&am…

ssm基于JAVA的酒店管理系统的设计与实现

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 第1章 绪论 1 1.1 选题动因 1 1.2 目的和意义 1 1.3 论文结构安排 2 第2章 开发环境与技术 3 2.1 S…

【AI知识点】置信区间(Confidence Interval)

置信区间&#xff08;Confidence Interval, CI&#xff09; 是统计学中用于估计总体参数的范围。它给出了一个区间&#xff0c;并且这个区间包含总体参数的概率等于某个指定的置信水平&#xff08;通常是 90%、95% 或 99%&#xff09;。与点估计不同&#xff0c;置信区间通过区…

i春秋云境靶场之CVE-2022-26965

1.环境搭建 提示我们后台存在rce,也就是命令执行漏洞 2.访问环境 cm - cmshttp://eci-2zeh0yf0ohu88wr26unq.cloudeci1.ichunqiu.com/ 我们可看到admin,我们点击&#xff0c;发现是一个登录页面&#xff0c;我们输入弱口令admin,登录成功 3.文件上传 我们在选项——选择主题…

C++:图的遍历

一、简介 图的遍历通常有深度优先遍历和广度优先遍历两种方式&#xff0c;这两种遍历次序对无向图和有向图都使用。 本文分别介绍基于邻接矩阵和邻接表的图的深度优先遍历和广度优先遍历&#xff0c;对于邻接矩阵和邻接表不熟悉的可翻阅&#xff1a;C&#xff1a;图的存储结构及…

dockerpull

20241006更新&#xff0c;亲测可用。 注意&#xff1a;这个方法随时可能会失效。 编辑配置文件&#xff0c;修改镜像源&#xff1a; vi /etc/docker/daemon.json {"registry-mirrors": ["https://do.nark.eu.org","https://dc.j8.work","…

TypeScript 第三部分 扩展

1. 声明文件 主要作用&#xff1a; 类型声明&#xff1a;为库或模块提供类型信息。全局声明&#xff1a;为全局作用域中的类型和变量提供声明。类型兼容性&#xff1a;确保第三方库或自定义代码的类型正确性。代码提示与检查&#xff1a;在开发环境中提供更好的代码提示和类型…

Sollong手机——一站式Web3生态解决方案

从定义上讲&#xff0c;Web3公司也属于互联网公司&#xff0c;不过与传统互联网公司相比&#xff0c;他们有一个很明显的特征&#xff1a;他们不断尝试做去中心化的事&#xff0c;一步步将数据和金融的控制权从美联储&#xff08;央行和金融机构&#xff09;、苹果&#xff08;…

2024/10/6周报

文章目录 摘要Abstract广西的一些污水处理厂工艺解析1. A/O工艺&#xff08;厌氧-缺氧-好氧工艺&#xff09;2. 氧化沟工艺3. MBR工艺&#xff08;膜生物反应器&#xff09;4. SBR工艺&#xff08;序批式活性污泥法&#xff09;5. 生物接触氧化法 其它补充一体化改良氧化沟工艺…

Linux的基础指令(下)

压缩包 这里不为打包和压缩做仔细的区分&#xff1b; 打包&#xff1a; 文件合并&#xff1b; 主要目的是在文件传输&#xff0c;移动时&#xff0c;能有效减少文件的缺失&#xff1b; 压缩&#xff1a;为了减小文件体积&#xff0c;内存&#xff1b; 主要目的是减小使用体…

在JS中定义和使用Vector2

概述 Vector2是GDSCript中表示二维向量的类型&#xff0c;你会发现无论在任何编程语言中&#xff0c;只要你想很好的实现2D绘图以及几何和物理相关&#xff0c;Vector2是你必须要实现的一个类。我之前学C时就写过一个C的版本。 本篇就介绍我自己在JavaScript中定义的Vector2类…

基于ssm 框架的java 开发语言的 在线教育学习平台系统设计与实现 源码 论文

博主介绍&#xff1a;专注于Java&#xff08;springboot ssm springcloud等开发框架&#xff09; vue .net php phython node.js uniapp小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆…

AI周报(9.29-10.5)

AI应用-Elayne公司临终规划和自动化遗产结算 创业公司Elayne成立于2023年&#xff0c;由Adria Ferrier和Jake Grafenstein共同创立&#xff0c;Adria Ferrier担任CEO&#xff0c;总部位于科罗拉多州丹佛市。 Elayne公司专注于遗产规划和结算领域&#xff0c;通过人工智能技术…

实验4 循环结构

1、判断素数 【问题描述】从键盘输入一个大于1的正整数&#xff0c;判断是否为素数 【输入形式】输入一个正整数 【输出形式】输出该数是否为素数 【样例输入】10 【样例输出】10 is not a prime number 【样例说明】样例2 输入&#xff1a;-10 输出&#xff1a;error! #de…

实景三维赋能矿山安全风险监测预警

随着科技的不断进步&#xff0c;实景三维技术在矿山安全风险监测预警中的应用越来越广泛&#xff0c;它为矿山安全管理带来了革命性的变革。 一、矿山安全现状 矿山作为国家重要的能源和原材料基地&#xff0c;其安全生产直接关系到国民经济的发展和社会的稳定。然而&#xf…