FloodFill算法(DFS+BFS)【上】

news2024/9/24 13:15:27

文章目录

    • FloodFill算法
    • 733. 图像渲染
      • 题目解析
      • 算法原理
      • 代码实现
    • 200. 岛屿数量
      • 题目解析
      • 算法原理
      • 代码实现
    • 695. 岛屿的最大面积
      • 题目解析
      • 算法原理
      • 代码实现
    • 130. 被围绕的区域
      • 题目解析
      • 算法原理
      • 代码实现

FloodFill算法

FloodFill算法,中文名叫洪水灌溉

image-20240912220506133

这些模拟一块区域,正数部分表示凸起部分,负数部分表示凹陷部分,在“下雨/发大水”的时候,哪些区域会被覆盖。

这类一般需要解决哪些区域会“填上水”,一共多少块区域或者最大的区域是多少。

image-20240912220815880

它的本质都是在区域里面性质相同的连通块

解决这类问题,可以用两种方式:

  • DFS:深度优先遍历,从某一个点一直走,走到不能再走就返回
  • BFS:宽度优先遍历,从一个点开始,一层一层走

733. 图像渲染

题目链接:733. 图像渲染

题目解析

题目给我们一个起始位置,把与它相连且像素值相同的改成newColor

image-20240912221645556

算法原理

DFS:

一条路走到底,走之前先修改数据,走不了然后回溯。

稍微注意一下,然后起始值和目标值一样,可能会走重复的路。

所以需要判断一下,如果相同,直接返回

image-20240912224430691

BFS:

从起始位置(1, 1)开始,一层一层向外扩展

image-20240912222520872

这扩展的时候,就可以修改数据了

代码实现

DFS:

class Solution {
public:
    int m,n;
    int color;
    int target;
    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)
    {
        color = _color;
        if(image[sr][sc] == color)  return image;
        m = image.size();
        n = image[0].size();
        target = image[sr][sc];
        dfs(image, sr, sc);
        return image;
    }


    void dfs(vector<vector<int>>& image, int pos_x, int pos_y)
    {
        image[pos_x][pos_y] = color;
        for(int k = 0; k < 4; k++)
        {
            int x = dx[k] + pos_x;
            int y = dy[k] + pos_y;
            if(x >= 0 && x < m && y >= 0 && y < n && image[x][y] == target)
            {
                //image[x][y] = color;
                dfs(image, x, y);
            }
        }
        //return;
    }
};

BFS:

class Solution {
public:
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color)
    {
        //起始位置像素值
        int prev = image[sr][sc];  
        if(prev == color)   return image;

        int m = image.size();
        int n = image[0].size();
        queue<pair<int, int>> 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 = dx[i] + a;
                int y= dy[i] + b;
                if(x >= 0 && x < m && y >= 0 && y < n && image[x][y] == prev)     
                {
                    q.push({x, y});
                }
            }
        }
        return image;
    }
};

200. 岛屿数量

题目链接:200. 岛屿数量

题目解析

题目的意思就是看有几块连通区域

算法原理

从左往右扫描这个矩阵,当第一次遇到“陆地”的时候,就找到与这块陆地连接的区域

为了避免回溯/扩展回去,两种方法:

  1. 将原数组修改
  2. 采用一个同等规模的bool vis[][]数组,表示truefalsetrue扫描过,false未扫描

代码实现

DFS:

class Solution {
public:
    bool vis[301][301];
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
    int m, n;
    int ret = 0;
    int numIslands(vector<vector<char>>& 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])
                {
                    ret++;
                    dfs(grid, i, j);
                }
            }
        }
        return ret;
    }

    void dfs(vector<vector<char>>& grid, int i, int j)
    {
        vis[i][j] = true;
        for(int k = 0; k < 4; k++)
        {
            int x = i + dx[k];
            int y = j + dy[k];
            if(x >= 0 && x < m && y >=0 && y < n && grid[x][y] == '1' && !vis[x][y])
            {
                dfs(grid, x, y);
            }
        }
    }
};

BFS:

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

    }
};

695. 岛屿的最大面积

题目链接:695. 岛屿的最大面积

题目解析

给我们一个二进制矩阵表示岛屿,其中1表示岛屿、0表示水。

让我们找出面积最大的岛屿(上下左右连通)

算法原理

image-20240915214352834

从左往右、从上到下扫描一下矩阵,当遇到没有遍历过的1的时候,然后就进行DFS/BFS:

  • 进入一次dfs,count++,遍历结束之后,就是岛屿面积,只需找出最大值即可
  • bfs时,加入一次队列,count++,完毕之后,就知道了面积

代码实现

DFS:

class Solution {
public:
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, -1, 1};
    bool vis[51][51];
    int ret, count = 0;
    int m, n;
    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])
                {
                    count = 0;
                    ret = max(ret, dfs(grid, i, j));
                }
            }
        }
        return ret;
    }

    int dfs(vector<vector<int>>& grid, int i, int j)
    {
        vis[i][j] = true;
        count++;
        for(int k = 0; k < 4; k++)
        {
            int x = i + dx[k];
            int y = j + dy[k];
            if(x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && grid[x][y] == 1)
            {
                dfs(grid, x, y);
            }
        }
        return count;
    }
};

BFS:

class Solution {
public:
    bool vis[51][51];
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
    int m;
    int n;
    int maxAreaOfIsland(vector<vector<int>>& grid)
    {
        m = grid.size();
        n = grid[0].size();
        int ret = 0;
        for(int i = 0; i < m; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if(grid[i][j] && !vis[i][j])
                {
                    ret = max(ret, bfs(grid,i, j));
                }
            }
        }
        return ret;
    }

    int bfs(vector<vector<int>>& grid, int i, int j)
    {
        int count = 0;
        queue<pair<int, int>> q;
        q.push({i, j});
        vis[i][j] = true;
        count++;
        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])
                {
                    count++;
                    q.push({x, y});
                    vis[x][y] = true;
                }
            }
        }
        return count;
    }
};

130. 被围绕的区域

题目链接:130. 被围绕的区域

题目解析

给我们一个矩阵,里面只有XO,找出被X包围的O

必须是上下左右都有X才是被包围

算法原理

这里可以直接遍历,遇见O就修改成X,但是这样如果边界有X,此时又要返回去,重新改回来,这要涉及分情况讨论。

正难则反:

遍历四条边,如果有O,对边上的O做一次dfs/bfs,然后把这些连通块修改成一个无关的字符,然后遍历一次矩阵,此时的O一定是被包围的,直接修改即可

image-20240915221105256

代码实现

DFS:

class Solution {
public:
    int m, n;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    void solve(vector<vector<char>>& board)
    {
        m = board.size();
        n = board[0].size();
        for(int i = 0; i < m; i++)
        {
            for(int j = 0; j < n; j++)
            {
                if((i == 0 || j == 0 || i == m-1 || j == n-1) && board[i][j] == 'O')
                {
                    //cout << 1 << endl;
                    dfs(board, i, j);
                }
            }
        }

        for(auto& e : board)
        {
            for(auto&ch : e)
            {
                if(ch == '.')
                    ch = 'O';
                else
                    ch = 'X';
            }
        }
    }

    void dfs(vector<vector<char>>& board, int i, int j )
    {
        board[i][j] = '.';
        for(int k = 0; k < 4; k++)
        {
            int x = dx[k] + i;
            int y = dy[k] + j;
            if(x >= 0 && y >= 0 && x < m && y < n && board[x][y] == 'O')
            {
                dfs(board, x, y);
            }
        }
    }
};

BFS:

class Solution {
public:
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, -1, 1};
    int m;
    int n;
    char label = '.';
    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] == label)
                {
                    board[i][j] = 'O';
                }
                else
                {
                    board[i][j] = 'X';
                }
            }
        }
    }

    void bfs(vector<vector<char>>& board, int i, int j)
    {
        queue<pair<int, int>> q;
        q.push({i, j});
        board[i][j] = label;
        while(q.size())
        {
            auto [a, b] = q.front();
            q.pop();
            for(int k = 0; k < 4; k++)
            {
                int x = dx[k] + a;
                int y = dy[k] + b;
                if(x >= 0 && x < m && y > 0 && y < n && board[x][y] == 'O')
                {
                    board[x][y] = label;
                    q.push({x, y});
                }
            }
        }

    }
};

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

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

相关文章

SQL进阶技巧:火车票相邻座位预定一起可能情况查询算法 ?

目录 0 场景描述 1 数据准备 2 问题分析 2.1 分析函数法 2.2 自关联求解 3 小结 如果觉得本文对你有帮助&#xff0c;那么不妨也可以选择去看看我的数字化建设通关指南博客专栏 &#xff0c;或许对你更有用。专栏原价99&#xff0c;现在活动价29.9&#xff0c;按照阶梯…

深圳前海港湾学校天桥下的免费停车点探寻

​最近开车去桂湾公园停车场的路上&#xff0c;看到有个天桥下有很多车停着&#xff0c;关键是这个地方离我搬砖的前海卓越写字楼还近&#xff0c;要是有时候桂湾公园停车位满了&#xff0c;停不进去的时候&#xff0c;是不是可以去这个天气下薅免费停车的羊毛&#xff1f;哈哈…

基于YOLO深度学习和百度AI接口的手势识别与控制项目

基于YOLO深度学习和百度AI接口的手势识别与控制项目 项目描述 本项目旨在开发一个手势识别与控制系统&#xff0c;该系统能够通过摄像头捕捉用户的手势&#xff0c;并通过YOLO深度学习模型或调用百度AI接口进行手势识别。识别到的手势可以用来控制计算机界面的操作&#xff0…

【OJ刷题】双指针问题4

这里是阿川的博客&#xff0c;祝您变得更强 ✨ 个人主页&#xff1a;在线OJ的阿川 &#x1f496;文章专栏&#xff1a;OJ刷题入门到进阶 &#x1f30f;代码仓库&#xff1a; 写在开头 现在您看到的是我的结论或想法&#xff0c;但在这背后凝结了大量的思考、经验和讨论 目录 1…

Google宣布所有英语语种的Gemini Live用户现可免费使用

谷歌在Pixel 9系列手机的发布会上&#xff0c;同步推出了Gemini Live&#xff0c;该服务提供了一种移动对话体验&#xff0c;让用户和Gemini展开自由流畅的对话。Google现在宣布&#xff0c;所有使用英语的Gemini Live用户&#xff0c;可免费使用&#xff0c;此前为需要Advance…

RockyLinux-软件实现RAID5

一、背景 RAID&#xff08;Redundant Array of Independent Disks&#xff0c;独立磁盘冗余阵列&#xff09;是一种将多个物理硬盘驱动器组合成单一逻辑单元的技术&#xff0c;目的是提高存储性能、可靠性和/或数据冗余度。虽然早期的名字中包含“独立”&#xff08;Independen…

【C++】stack 和 queue 以及 容器适配器

文章目录 一、stack1.1 stack的使用1.2 stack的模拟实现 二、queue2.1 queue的使用2.2 queue的模拟实现 三、优先级队列1.优先级队列的介绍2. priority_queue的使用的使用3.模拟实现优先级队列 四、 容器适配器1.STL标准库中stack和queue的底层结构2.deque&#xff08;双端对列…

Unity3D 发布后去除Development Build显示

问题描述&#xff1a; Build后在视野右下角看到“Development Build”白色小字 解决方法&#xff1a; build时不勾选Development Build项 PS: 游戏开发unity杂项知识系列&#xff1a;build时Development Build的作用_unity development build-CSDN博客

结构体的内存对齐

对⻬规则&#xff1a; 1.结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处 2.其他成员变量要对⻬到某个数字&#xff08;对⻬数&#xff09;的整数倍的地址处。 对⻬数编译器默认的⼀个对⻬数与该成员变量⼤⼩的较⼩值。 但一些编译器下并没有默认对其数 3.结…

ElK 8 收集 Nginx 日志

1. 说明 elk 版本&#xff1a;8.15.0 2. 启个 nginx 有 nginx 可以直接使用。我这里是在之前环境下 docker-compose.yml 中启动了个 nginx&#xff1a; nginx:restart: alwaysimage: nginx:1.26.1ports:- "80:80"- "443:443"volumes:#- ./nginx/html:/…

探索Python轻量级数据库:TinyDB的奇妙之旅

文章目录 探索Python轻量级数据库&#xff1a;TinyDB的奇妙之旅背景&#xff1a;为何选择TinyDB&#xff1f;什么是TinyDB&#xff1f;如何安装TinyDB&#xff1f;简单库函数使用方法场景应用常见Bug及解决方案总结 探索Python轻量级数据库&#xff1a;TinyDB的奇妙之旅 背景&…

H5 three.js 实现六年级观察物体

o(&#xffe3;▽&#xffe3;)ブ 我又带着新的demo来啦~ 预览 功能点 立方体的阴影 立方体的添加 位置记录 最大限制 三视图展示 立方体的移除 答题模式 随机出题 题库出题 源码 注释算是比较全了&#xff0c;可能部分会有点绕&#xff0c;还能够再优化一下~ <!DOCTYPE …

51单片机+proteus+(DS1302+DS18B20)

目录 1.温度传感器检测&#xff08;DS18B20&#xff09; 1.1基本概念 1.1.1 DS18B20的简介 1.1.2 DS18B20的框图 ​编辑 1.1.3 DS18B20的指令 1.1.4 总线时序协议 1.2代码 1.2.1DS18B20的初始化代码 1.2.2DS18B20的读代码 1.2.3DS18B20的写时序 ​编辑 1.2.4DS18B20…

[C语言]第九节 函数一基础知识到高级技巧的全景探索

目录 9.1 函数的概念 9.2 库函数 9.2.1 标准库与库函数 示例&#xff1a;常见库函数 9.2.2 标准库与头文件的关系 参考资料和学习工具 如何使用库函数 ​编辑 9.3 ⾃定义函数 9.3.1 函数的语法形式 9.3.2函数的举例 9.4 实参与形参 9.4.1 什么是实参&#xff1f; 9…

嵌入式单片机中数码管基本实现方法

1. 点亮数码管 本节课利用已经学习的LED知识去控制一个8位数码管。 本节的原理比较简单。不需要多少时间讲。 更多时间是跟大家一起编码调试,从中学习一些编码思路和学习方法。 1.1. 什么是数码管 数码管是什么?下图就是一个数码管 从硬件上个看,其实就是8个LED组合…

Python实用的27个实例,涵盖从基础到进阶的所有领域!

Python 是一种广泛使用的高级编程语言&#xff0c;以其简洁的语法和丰富的库支持而受到开发者们的喜爱。以下列出了 27 个实用的 Python 实例&#xff0c;涵盖从基础到进阶的不同领域&#xff0c;帮助你提升编程技能。 1. 打印 "Hello, World!" print("Hello,…

企业微信如何利用群聊机器人定时推送消息

背景&#xff1a;公司其他部门有在群聊中新建机器人并定时推送消息的需求&#xff0c;webhook已准备好 1、准备一台服务器或者虚拟机&#xff0c;编写脚本 [rootlocalhost opt]# vim crontab.sh curl https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key4d38964b-04f2-44…

【Arduino】国产arduino驱动

买的国产 arduino&#xff0c;如果 windows识别不到。或者用 Arduino自带的Driver程序仍不能驱动。又不想用驱动精灵&#xff0c;可以直接安装驱动程序 99%大概率是CH340芯片&#xff0c;驱动下载连接如下。 你可以从 WCH 官方网站 下载并安装 CH340 驱动程序 安装即可用&am…

进阶岛 renwu5: 茴香豆:企业级知识问答工具实践闯关任务

进阶岛 renwu5: 茴香豆&#xff1a;企业级知识问答工具实践闯关任务 renwu: https://kkgithub.com/InternLM/Tutorial/blob/camp3/docs/L2/Huixiangdou/task.md 在 InternStudio 中利用 Internlm2-7b 搭建标准版茴香豆知识助手&#xff0c;并使用 Gradio 界面完成 2 轮问答&a…

什么是java的spi?

Java SPI&#xff08;Service Provider Interface&#xff09;是一种提供服务发现机制的设计模式&#xff0c;允许在运行时动态地发现、加载和替换服务的实现。SPI机制的核心思想是&#xff1a;通过接口定义服务&#xff0c;并且使用外部的实现类来提供该服务的具体功能。 目录…