BFS:FloodFill算法

news2024/11/26 5:34:13

文章目录

  • FloodFill算法简介
  • 1.图像渲染
  • 2.岛屿数量
  • 3.岛屿的最大面积
  • 4.被围绕的区域
  • 总结

在这里插入图片描述

FloodFill算法简介

Flood Fill算法是一种用于确定与某个给定节点相连的区域的算法,常用于计算机图形学和图像处理。该算法可以用于诸如填充多边形、检测连通区域等任务。Flood Fill算法有多种实现方式,其中最常见的是递归方法和使用栈或队列的迭代方法。

基本思想
Flood Fill算法从一个初始像素开始,检查该像素的颜色。如果颜色匹配(即需要填充的颜色),则将其填充为新的颜色,然后对相邻的像素重复这一过程,直到所有相连的匹配像素都被填充为止。

在这里插入图片描述
FloodFill算法也叫洪水灌溉法,上图中0表示岛屿,1表示海洋,如果要我们求岛屿的个数的话就可以用洪水灌溉法则。

在这里插入图片描述

灌溉之后就像上面一样。
接下来,我们来练习几道题熟悉一下FloodFill算法。

1.图像渲染

题目链接
题目:

在这里插入图片描述

样例输入和输出:

在这里插入图片描述

这道题的意思很简单,就是我们固定一个位置,这个位置的坐标是[sr,sc]这个位置周围的和这个这个区块数字相同数都会被变成新的数字。
以上面这个例子为例,初始坐标是中间坐标,那么渲染的区块就是:
在这里插入图片描述
在这里插入图片描述
如果利用FloodFill算法的话,我们按顺序灌溉应该是1->2->3->4。

算法原理:
利用BFS的FloodFill算法,这个算法我们只需要借助队列,每次入队列的时候改变当前节点的值。

代码展示:

class Solution {
public:
    typedef pair<int,long> PIL;
    //定义一个方向数组,上下左右四个位置
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) 
    {
        //标记一下需要修改的像素值
        int prev=image[sr][sc];
        int m=image.size();
        int n=image[0].size();
        if(prev==color)
        {
            return image;//处理边界情况
        }
        queue<PIL> q;
        q.push({sr,sc});
        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]==prev)
                {
                    q.push({x,y});
                }
            }
        }
        return image;
    }
};

2.岛屿数量

题目链接
题目:

在这里插入图片描述

样例输入和输出:

在这里插入图片描述

我们来看示例1:
在这里插入图片描述
这道题1是岛屿,0是海,然后这个数组的周围默认都是海。

算法原理:
这道题和上道题的思路是一样的,但是还多出来一步,就是当我们利用bfs来遍历数组的时候,假如我们从第一个位置开始遍历,遍历了一遍,记录了一个岛屿,但是我们第二次遍历的时候从第二个位置的1开始遍历,但是第二个位置的1是属于第一个岛屿的,所以这里就会产生重复,解决这种重复问题的办法就是开一个bool类型的vis数组,这个数组的大小和给定的数组的大小是相同的,我们每访问一个岛屿就将这个岛屿上对应的vis变为true,表示我们已经访问过这个节点了,所以这里进行bfs的条件多了一个不仅需要这个节点的值是1,还需要这个节点对应的vis数组是true。

代码展示:

class Solution {
public:
    typedef pair<int,int> PIL;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    bool vis[301][301];
    int ret=0;
    int m,n;
    void bfs(vector<vector<char>>& grid,int i,int j)
    {
        queue<PIL> q;
        q.push({i,j});
        vis[i][j]=false;
        while(q.size())
        {
            auto [a,b]=q.front();
            q.pop();
            for(int k=0;k<4;k++)
            {
                int x=a+dx[k];
                int y=b+dy[k];
                if(x < m && x >= 0 && y >= 0&&y<n&&grid[x][y]=='1'&&vis[x][y]==false)
                {
                    vis[x][y]=true;
                    q.push({x,y});
                }
            }
        }
    }
    int numIslands(vector<vector<char>>& grid) 
    {
        m=grid.size();
        n=grid[0].size();
        for(int i=0;i<grid.size();i++)
        {
            for(int j=0;j<grid[i].size();j++)
            {
                if(grid[i][j]=='1'&&vis[i][j]==false)
                {
                    bfs(grid,i,j);//将这个陆地标记一下
                    ret++;
                }
            }
        }
        return ret;
    }
};

3.岛屿的最大面积

题目链接
题目:

在这里插入图片描述

样例输入和输出:

在这里插入图片描述

这道题的背景和上一道题是一样的,但是这道题不是让我们求岛屿的数量而是让我们求所有岛屿中面积最大的那个岛屿大面积

算法原理:
这道题需要的变量和上道题也是一样的,但是唯一不同的一点是上一道题是void,这道题是int,所以我们需要记录每次BFS的结果,我们用S记录每次BFS的结果,然后每次BFS之后,和前一次求出来的面积进行比较,最后直接返回最大值。

代码展示:

class Solution {
public:
    typedef pair<int,int> PIL;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    bool vis[51][51];
    int m,n;
    int S;
    int bfs(vector<vector<int>>& grid,int i,int j)
    {
        int Sum=0;
        queue<PIL> q;
        q.push({i,j});
        Sum++;
        vis[i][j]=true;
        while(q.size())
        {
            auto [a,b]=q.front();
            q.pop();
            for(int k=0;k<4;k++)
            {
                int x=a+dx[k];
                int y=b+dy[k];
                if(x>=0&&x<m&&y>=0&&y<n&&grid[x][y]==1&&vis[x][y]==false)
                {
                    vis[x][y]=true;
                    q.push({x,y});
                    Sum++;
                }
            }
        }
        return Sum;
    }
    int maxAreaOfIsland(vector<vector<int>>& grid) 
    {
        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&&vis[i][j]==false)
               {
                    int S1=bfs(grid,i,j);
                    if(S<S1)
                    {
                        S=S1;
                    }
               }
            }
        }
        return S;
    }
};

4.被围绕的区域

题目链接
题目:

在这里插入图片描述

样例输入和输出:

在这里插入图片描述

这道题给出的二维数组中的值只有X和O,这道题的意思就是让我们修改被x包围的O为x,然后边界的联通区域不需要修改。
我们用一个例子来表示上面的题意:
在这里插入图片描述

蓝色区域表示不能修改的边界联通区域,灰色区域表示被X围住的中间的需要修改的联通区域。

算法原理,如果这道题我们直接正面做的话,很难,因为当我们进行BFS的时候,我们并不知道这块区域是边界联通的区域,就像下面这种情况:
在这里插入图片描述
上面这种情况,当我们从第一个位置开始BFS我们到后面才知道这个联通区域是边界区域,但是我们又不能倒过去找,所以我们只能先标记这个边界区域,然后再用一次BFS对可修改区域进行修改,所以这里我们先对边界区域进行遍历,先把边界区域修改为另一个字符,这里我们将这个字符定义为’*'修改了之后,我们只需要对这个二维数组遍历一遍,将O修改为X,将 *修改为O即可。

代码展示:

class Solution {
public:
    typedef pair<int,int> PII;
    int m,n;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    void bfs(vector<vector<char>>& board,int i,int j)
    {
        queue<PII> q;
        q.push({i,j});
        board[i][j]='*';
        while(q.size())
        {
            auto [a,b]=q.front();
            q.pop();
            for(int k=0;k<4;k++)
            {
                int x=a+dx[k];
                int y=b+dy[k];
                if(x>=0&&x<m&&y>=0&&y<n&&board[x][y]=='O')
                {
                    q.push({x,y});
                    board[x][y]='*';
                }
            }
        }
    }
    void solve(vector<vector<char>>& board) {
        m=board.size();
        n=board[0].size();
        for(int j=0;j<n;j++)
        {
            if(board[0][j]=='O')bfs(board,0,j);
            if(board[m-1][j]=='O')bfs(board,m-1,j);
        }
        for(int i=0;i<m;i++)
        {
            if(board[i][0]=='O')bfs(board,i,0);
            if(board[i][n-1]=='O')bfs(board,i,n-1);
        }
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(board[i][j]=='O')
                board[i][j]='X';
                if(board[i][j]=='*')
                board[i][j]='O';
            }
        }
    }
};

总结

Flood Fill算法在图像处理和计算机图形学中扮演着重要角色。无论是用于简单的填色任务,还是复杂的区域检测,这一算法都展示了其强大的功能。本文详细介绍了Flood Fill算法的基本思想,并提供了递归和迭代两种实现方式。递归方法虽然简单直观,但在处理较大图像时可能会遇到递归深度的限制;而迭代方法则通过显式管理待填充的像素,克服了这一问题。

通过这两种实现方法的比较,我们不仅了解了Flood Fill算法的原理,也掌握了如何选择合适的实现方式来应对不同的应用场景。希望这篇博客能帮助大家更好地理解和应用Flood Fill算法,在实际项目中解决相关问题。

如果您有任何问题或需要进一步讨论,欢迎在评论区留言。感谢您的阅读!

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

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

相关文章

淘宝订单物流信息获取:详细操作指南

一、前言 淘宝作为中国最大的电商平台之一&#xff0c;其订单管理系统为商家提供了丰富的接口&#xff0c;用于查询、管理和跟踪订单信息。本指南将详细介绍如何通过淘宝订单接口获取物流信息&#xff0c;帮助商家更好地管理订单和提供优质的物流服务。 二、获取物流信息的步…

低代码开发平台助力审计工作智能化

在数字化转型的浪潮中&#xff0c;低代码平台以其高效、灵活的特性&#xff0c;成为推动审计作业现代化的关键工具。审计作业低代码平台&#xff0c;通过简化开发流程&#xff0c;使得非技术背景的审计人员也能快速构建和部署审计应用&#xff0c;极大地提升了审计效率和质量。…

2024年十大数据集成工具和软件应用场景解析

详细阐述了十大数据集成工具及其优缺点&#xff1a; 数据集成的挑战 在当今的商业环境中&#xff0c;企业常常面临着数据分散、系统孤立的难题。传统的数据集成方式&#xff0c;就像一张复杂的蜘蛛网&#xff0c;难以理顺&#xff0c;令人头痛不已。 数据孤岛: 各个业务系统独立…

idea插件开发之一起来开发个打印方法入参和返回值的插件吧!

写在前面 源码 。 在开发过程中为了调试代码我们就可能就需要知道某个方法入参的值是什么&#xff0c;或者是返回值是什么。此时&#xff0c;我们的解决办法一般都是debug&#xff0c;但是debug的效率说实话其实是不高的&#xff0c;特别是不断的调试&#xff0c;不断的debug。…

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(十五)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 23 - 24 节&#xff09; P23《22.Stage模型-基本概念》 一个应用可以有很多的能力&#xff0c;每个能力可以成为一个 Ability Mod…

百元价位真无线蓝牙耳机怎么选?四款宝藏平价机型盘点

在繁忙的现代生活中&#xff0c;真无线蓝牙耳机凭借其便携性、无线连接以及出色的音质&#xff0c;已经成为了许多人的必备配件&#xff0c;面对市场上琳琅满目的产品&#xff0c;如何在百元价位内挑选出一款性价比高、性能出色的真无线蓝牙耳机&#xff0c;确实是一个值得深思…

CATIA入门操作案例——理工男的浪漫:如何画一支玫瑰花送给女朋友?如何画一束玫瑰花?

目录 引出画玫瑰花画中间的花蕾画花瓣在零件设计模式下&#xff0c;厚轮廓画曲面实体 进行圆周阵列&#xff0c;完整径向对花瓣进行倒角再画一层花瓣画叶子在新的几何体里面绘制叶子 叶子阵列画花杆使用肋条画杆子 将两个零件体进行合并 一支玫瑰花画一束玫瑰花先平移一下复制粘…

异步任务使用场景与实践

异步任务使用场景 根据同步/异步方式划分场景&#xff0c;各场景下常用的技术方案如下&#xff1a; 方式实现特点缺点同步HTTP RPC Cache etc.指标&#xff1a;RT、QPS、TPS、缓存命中率 等&#xff1b; 关注&#xff08;准&#xff09;实时数据&#xff0c;用户可交互1. 处…

微服务架构-线上治理、线下治理与架构演进

目录 一、线上治理 1.1 概述 1.2 线上预案体系 1.2.1 概述 1.2.2 变更引起的故障 1.2.3 流量和容量变化引起的故障 1.2.4 依赖故障 1.2.5 机房、网络等硬件和环境故障 1.2.6 其他 1.2.7 故障的场景化 1.3 基于Metric的预案自动触发 1.4 治理参数动态调整 1.4.1 举例…

dial tcp 10.96.0.1:443: connect: no route to host

1、创建Pod一直不成功&#xff0c;执行kubectl describe pod runtime-java-c8b465b98-47m82 查看报错 Warning FailedCreatePodSandBox 2m17s kubelet Failed to create pod sandbox: rpc error: code Unknown desc failed to setup network for…

算力之困,大模型何解?

互联网企业选择大模型合作伙伴之时&#xff0c;首要考虑的因素是算力。 大模型本身就是巨量参数“力大砖飞”的结晶&#xff0c;也就是说大模型与大算力密不可分。 发展到今天&#xff0c;国内的大模型在对话层面&#xff0c;已经与GPT-3.5接近&#xff0c;但在复杂指令层面与…

使用nvm安装node.js ,方便管理多个版本的node.js,且程序添加和卸载页面也不会出现多个版本的node.js软件(是一个都不会出现)

首先下载和安装nvm windows 安装 nvm&#xff1a; 需要先把本地安装的Node.js卸载&#xff0c;然后再下载nvm&#xff0c;地址&#xff1a; https://github.com/coreybutler/nvm-windows/releases 一般情况&#xff0c;找到最新版本&#xff0c;然后下载nvm-setup.exe文件就可以…

WACV2024论文3D相关速览48篇

WACV2024 3D相关论文阅读 Paper1 Self-Supervised Edge Detection Reconstruction for Topology-Informed 3D Axon Segmentation and Centerline Detection 摘要小结: 许多基于机器学习的轴突追踪方法依赖于带有分割标签的图像数据集。这需要领域专家的手动标注&#xff0c;既…

DP:完全背包+多重背包问题

完全背包和01背包的区别就是&#xff1a;可以多次选 一、完全背包&#xff08;模版&#xff09; 【模板】完全背包_牛客题霸_牛客网 #include <iostream> #include<string.h> using namespace std; const int N1001; int n,V,w[N],v[N],dp[N][N]; //dp[i][j]表示…

从社交网络到元宇宙:Facebook的战略转型

随着科技的迅猛发展和数字化时代的深入&#xff0c;社交网络已不再局限于简单的信息交流和社交互动&#xff0c;而是逐步向更广阔、更深远的虚拟现实空间——元宇宙&#xff08;Metaverse&#xff09;转变。作为全球最大的社交网络平台之一&#xff0c;Facebook正在积极推动这一…

从新手小白到红酒大咖:解锁红酒品鉴的终极秘籍,升级之路全攻略

在五彩斑斓的饮品世界中&#xff0c;红酒以其深邃的色泽、丰富的口感和悠久的历史&#xff0c;吸引了无数人的目光。对于红酒的初学者来说&#xff0c;从小白到品鉴师的道路或许充满了未知与挑战&#xff0c;但只要掌握了正确的知识和方法&#xff0c;就能够轻松踏入这个美妙的…

RAG实操教程langchain+Milvus向量数据库创建你的本地知识库 二

Miluvs 向量数据库 关于 Milvui 可以参考我的前两篇文章 • 一篇文章带你学会向量数据库Milvus&#xff08;一&#xff09;[1]• 一篇文章带你学会向量数据库Milvus&#xff08;二&#xff09;[2] 下面我们安装 pymilvus 库 pip install --upgrade --quiet pymilvus如果你…

SpringBoot整合justauth实现多种方式的第三方登陆

目录 0.准备工作 1.引入依赖 2.yml文件 3. Controller代码 4.效果 参考 0.准备工作 你需要获取三方登陆的client-id和client-secret 以github为例 申请地址&#xff1a;Sign in to GitHub GitHub 1.引入依赖 <?xml version"1.0" encoding"UTF-8&quo…

代码走查的一个实例

1996年6月23日至7月1日&#xff0c;我被点名到四川某单位协助排查某系统的技术问题。 我不懂该系统的原理&#xff0c;也不懂硬件&#xff0c;只能从软件角度分析问题。 那时&#xff0c;我所在单位已经为一家美国公司做了3年的软件第三方独立验证和测试&#xff0c;从中学到…

【51单片机基础教程】点亮led

文章目录 前言51单片机点亮LED的原理硬件部分软件部分51单片机的寄存器编程步骤proteus仿真点亮一个led 点亮多个ledproteus仿真代码 流水灯 总结 前言 单片机&#xff08;Microcontroller Unit, MCU&#xff09;是一种集成电路&#xff0c;广泛应用于各种电子产品中。作为嵌入…