FloodFill

news2024/11/29 6:28:09

"绝境之中才窥见,Winner,Winner" 


FloodFill算法简介:

        floodfill又翻译成漫水填充。我们可以将下面的矩阵理解为一片具有一定高度的坡地,此时突发洪水,洪水会将高度<0的地方填满。        

        话句话来说,FloodFill算法是为了找出那些具有相同性质的区域。那我们现在就来看看一些经典的使用floodfill算法的题目。


图像渲染

(1) 题目解析        

                这类题目的代码部分,都是将模拟的过程转化成代码。

(2) 算法代码

dfs:

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

    void dfs(vector<vector<int>>& image, int i,int j,int newcolor)
    {
        // 从这一点出发,每一个方向去 递归相邻节点
        image[i][j] = newcolor;
        for(int k=0;k<4;++k)
        {
            int x=i+dx[k],y = j+dy[k];
            // 满足 要渲染更改的值 
            if(x>=0 && x<m && y>=0 && y<n && image[x][y] == prev)
            {
                dfs(image,x,y,newcolor);
            }
        }
    }
};

 bfs:       

class Solution {
public:
    typedef pair<int,int> PII;
    int m,n;
    int prev;
    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) {
        m = image.size(),n = image[0].size();
        if(image[sr][sc] == color) return image;
        // 当前位置会被修改为newcolor 这里是保存需要被渲染的值
        prev = image[sr][sc];
        bfs(image,sr,sc,color);
        return image;
    }

    void bfs(vector<vector<int>>& image, int i,int j,int newcolor)
    {
        queue<PII> que;
        image[i][j] = newcolor;
        que.push({i,j});
        while(que.size())
        {
            // 取出已经被渲染的位置,并将它的相邻位置,满足条件的 插入进队列
            auto [a,b] = que.front();
            que.pop();

            for(int k=0;k<4;++k)
            {
                int x=a+dx[k],y=b+dy[k];
                if(x>=0 && x<m && y>=0 && y<n && image[x][y] == prev)
                {
                    image[x][y] = newcolor;
                    que.push({x,y});
                }
            }
        }
    }
};

岛屿数量

(1) 题目解析        

注: 进行bfs或dfs时需要注意,防止统计已经遍历过的位置。我们有两种解决方法,其一就是对原数组内部的值进行修改,区别于目标条件,其二就是创建一个新的布尔数组,标记每一个遍历过的点。

(2) 算法代码

dfs:        

class Solution {
public:
    int m,n;
    bool vis[301][301];
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    int numIslands(vector<vector<char>>& grid) {
        m = grid.size(),n = grid[0].size();
        int count = 0;
        for(int i=0;i<m;++i)
            for(int j=0;j<n;++j)
            {
                // 遍历到岛屿进行一次dfs 并且这个位置没有被访问过
                if(grid[i][j] == '1' && !vis[i][j]) 
                {
                    count++;
                    vis[i][j] = true; // 标记
                    dfs(grid,i,j);
                }
            }
        
        return count;
    }

    void dfs(vector<vector<char>>& grid,int i,int j)
    {
        // 这里的dfs 只需将与(i,j) 相连的岛屿统计即可
        for(int k=0;k<4;++k)
        {
            int x=i+dx[k],y=j+dy[k];
            if(x>=0 && x<m && y>=0 && y<n && grid[x][y] == '1' && !vis[x][y])
            {
                vis[x][y] = true;
                dfs(grid,x,y);
            }
        }
    }
};

bfs:

    class Solution {
    public:
        int m,n;
        bool vis[301][301];
        int dx[4] = {0,0,1,-1};
        int dy[4] = {1,-1,0,0};
        int numIslands(vector<vector<char>>& grid) {
            m = grid.size(),n = grid[0].size();
            int count = 0;
            for(int i=0;i<m;++i)
                for(int j=0;j<n;++j)
                {
                    // 遍历到岛屿进行一次dfs 并且这个位置没有被访问过
                    if(grid[i][j] == '1' && !vis[i][j]) 
                    {
                        count++;
                        vis[i][j] = true; // 标记
                        bfs(grid,i,j);
                    }
                }
            
            return count;
        }

        void bfs(vector<vector<char>>& grid,int i,int j)
        {
            // 这里的bfs 只需将与(i,j) 相连的岛屿统计即可
            // bfs通常需要借助队列来实现
            queue<pair<int,int>> que;
            que.push({i,j});
            while(que.size())
            {
                auto [a,b] = que.front();
                que.pop();
                for(int k=0;k<4;++k)
                {
                    int x=a+dx[k],y=b+dy[k];
                    if(x>=0 && x<m && y>=0 && y<n && grid[x][y] == '1' && !vis[x][y])
                    {
                        vis[x][y] = true;
                        que.push({x,y});
                    }
                }
            }
        }
    };

岛屿的最大面积

(1) 题目解析        

        这道题和上个题目十分类似,只不过这道题目的结果是求这些岛屿的最大面积,所以,我们需要对相连岛屿数量进行统计,并最终返回一个最大值。

(2) 算法代码

dfs:

class Solution {
public:
    int m,n;
    bool vis[301][301];
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    int ret,count;
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        m = grid.size(),n = grid[0].size(),ret = 0;
        for(int i=0;i<m;++i)
            for(int j=0;j<n;++j)
            {
                // 遍历到岛屿进行一次dfs 并且这个位置没有被访问过
                if(grid[i][j] == 1 && !vis[i][j]) 
                {
                    count = 0;
                    dfs(grid,i,j);
                    ret = max(ret,count);
                }
            }
        return ret;
    }

    void 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],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 m,n;
    bool vis[301][301];
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    int ret,count;
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        m = grid.size(),n = grid[0].size(),ret = 0;
        for(int i=0;i<m;++i)
            for(int j=0;j<n;++j)
            {
                // 遍历到岛屿进行一次dfs 并且这个位置没有被访问过
                if(grid[i][j] == 1 && !vis[i][j]) 
                {
                    count = 0;
                    vis[i][j] = true; // 标记
                    bfs(grid,i,j);
                    ret = max(ret,count);
                }
            }
        return ret;
    }

    void bfs(vector<vector<int>>& grid,int i,int j)
    {
        // 这里的bfs 只需将与(i,j) 相连的岛屿统计即可
        // bfs通常需要借助队列来实现
        queue<pair<int,int>> que;
        que.push({i,j});
        count++;
        while(que.size())
        {
            auto [a,b] = que.front();
            que.pop();
            for(int k=0;k<4;++k)
            {
                int x=a+dx[k],y=b+dy[k];
                if(x>=0 && x<m && y>=0 && y<n && grid[x][y] == 1 && !vis[x][y])
                {
                    count++;
                    vis[x][y] = true;
                    que.push({x,y});
                }
            }
        }
    }
};


被围绕的区域

(1) 题目解析        

        但其实,我们发现这两个dfs本质是做同样的事情,但却因为判断边界,我们需要写两份不同的dfs,这是蛮麻烦的事情。我们换个思路,直接用一个dfs将边界的'O',进行过滤,并填上不相关的字符,再将整个数组遍历,遇到‘O’改为‘X’,遇到这个不相关的字符,改为'O'。

(2) 算法代码

dfs:

class Solution {
public:
    int m,n;
    bool vis[201][201];
    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 j=0;j<n;++j)
        {
            if(board[0][j] == 'O') dfs(board,0,j);
            if(board[m-1][j] == 'O') dfs(board,m-1,j);
        }

        // 第一列 最后一列
        for(int i=0;i<m;++i)
        {
            if(board[i][0] == 'O') dfs(board,i,0);
            if(board[i][n-1] == 'O') dfs(board,i,n-1);
        }

        for(int i=0;i<m;++i)
            for(int j=0;j<n;++j)
            {
                if(board[i][j] == '.') board[i][j] = 'O';
                else if(board[i][j] == 'O') board[i][j] = 'X';
            }
    }

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

bfs:        

class Solution {
public:
    int m,n;
    bool vis[201][201];
    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 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] == '.') board[i][j] = 'O';
                else if(board[i][j] == 'O') board[i][j] = 'X';
            }
    }

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

扫雷

(1) 题目解析        

        经典的扫雷游戏,至于玩法也就不过多解释。该题目考察的地方就在于,点击一个点之后,从这个 点开始进行对相邻领域的展开,我们可以采用dfs或bfs完成。

        当挖出的位置是一个雷,将这个位置标记成‘X’,游戏结束。当挖出的一个地方是空位置,你需要首先去相邻区域查找是否有雷,如果没有发现雷,则标记为'B',否则就需要将搜查到的雷的个数,标记在该位置处。

(2) 算法代码

dfs:

class Solution {
public:
    int m,n;
    bool vis[51][51];
    // 扫雷位置有八个位置需要被展开
    int dx[8] = {0,0,-1,1,-1,1,-1,1};
    int dy[8] = {1,-1,0,0,1,-1,-1,1};
    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
        m = board.size(),n = board[0].size();
        int i = click[0],j = click[1];
        if(board[i][j] == 'M')
            board[i][j] = 'X';
        else
            dfs(board,i,j);
        return board;
    }

    void dfs(vector<vector<char>>& board,int i,int j)
    {
        int count = 0;
        // 统计雷的数量
        for(int k=0;k<8;++k)
        {
            int x=i+dx[k],y=j+dy[k];
            if(x>=0 && x<m && y>=0 && y<n && board[x][y] == 'M') count++;
        }

        if(count){
            board[i][j] = count + '0';
        }
        else{
            board[i][j] = 'B';
            for(int k=0;k<8;++k)
            {
                int x=i+dx[k],y=j+dy[k];
                if(x>=0 && x<m && y>=0 && y<n && board[x][y] == 'E') dfs(board,x,y);
            }
        }
    }
};

bfs:        

class Solution {
public:
    int m,n;
    bool vis[51][51];
    // 扫雷位置有八个位置需要被展开
    int dx[8] = {0,0,-1,1,-1,1,-1,1};
    int dy[8] = {1,-1,0,0,1,-1,-1,1};
    vector<vector<char>> updateBoard(vector<vector<char>>& board, vector<int>& click) {
        m = board.size(),n = board[0].size();
        int i = click[0],j = click[1];
        if(board[i][j] == 'M')
            board[i][j] = 'X';
        else
            bfs(board,i,j);
        return board;
    }

    void bfs(vector<vector<char>>& board,int i,int j)
    {
        queue<pair<int,int>> que;
        que.push({i,j});
        vis[i][j] = true;

        while(que.size())
        {
            auto [a,b] = que.front();
            que.pop();
            
            int count = 0;
            // 统计雷的数量
            for(int k=0;k<8;++k)
            {
                int x=a+dx[k],y=b+dy[k];
                if(x>=0 && x<m && y>=0 && y<n && board[x][y] == 'M') count++;
            }

            if(count){
                board[a][b] = count + '0';
            }
            else{
                board[a][b] = 'B';
                for(int k=0;k<8;++k)
                {
                    int x=a+dx[k],y=b+dy[k];
                    if(x>=0 && x<m && y>=0 && y<n && board[x][y] == 'E')
                    {
                        // 这里改为'B' 避免被其他点统计到 队列中去
                        // 也可以使用 vis[x][y] = ture; 进行标记 不被统计 !!!
                        board[x][y] = 'B'; 
                        que.push({x,y});
                    }
                }
            }
        }
    }
};


本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~

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

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

相关文章

NX二次开发UF_CURVE_ask_trim 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_trim Defined in: uf_curve.h int UF_CURVE_ask_trim(tag_t trim_feature, UF_CURVE_trim_p_t trim_info ) overview 概述 Retrieve the current parameters of an a…

Java + openCV更换证件照背景色

最近在小红书上看到很多更换证件照背景色的需求&#xff0c;联想到以前自己也更换过证件照背景色而且还是付费的&#xff0c;碰巧最近在看一本书《JavaOpenCV高效入门》&#xff0c;于是查找资料&#xff0c;找到了通过技术解决这个需求的办法。 先看效果图&#xff08;图片来自…

OpenCV入门11——图像的分割与修复

文章目录 图像分割的基本概念实战-分水岭法(一)实战-分水岭法(二)GrabCut基本原理实战-GrabCut主体程序的实现实战-GrabCut鼠标事件的处理实战-调用GrabCut实现图像分割meanshift图像分割视频前后景分离其它对视频前后影分离的方法图像修复 图像分割是计算机视觉中的一个重要领…

window环境搭建StarRocksFE节点

StarRocks部署–源码编译 前言 ​ 注意:本文借用了一些其他文章的一些截图&#xff0c;同时自己做了具体的编译步骤&#xff0c;添加了一些新的内容 ​ 目标&#xff1a; 编译StarRocks2.5.13版本FE节点代码&#xff0c;在本地window环境运行&#xff0c;可以访问到8030界面…

频剪辑软件Corel VideoStudio 会声会影2024最新7大新全新功能解析

我很喜欢视频剪辑软件Corel VideoStudio 会声会影2024&#xff0c;因为它使用起来很有趣。它很容易使用&#xff0c;但仍然给你很多功能和力量。视频剪辑软件Corel VideoStudio 会声会影2023让我与世界分享我的想法&#xff01;“这个产品的功能非常多&#xff0c;我几乎没有触…

【数据中台】开源项目(2)-Wormhole流式处理平台

Wormhole 是一个一站式流式处理云平台解决方案&#xff08;SPaaS - Stream Processing as a Service&#xff09;。 Wormhole 面向大数据流式处理项目的开发管理运维人员&#xff0c;致力于提供统一抽象的概念体系&#xff0c;直观可视化的操作界面&#xff0c;简单流畅的配置管…

《已解决: ImportError: Keras requires TensorFlow 2.2 or higher 问题》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

vscode 使用git提交前端代码

1、项目初始化git 如果是从其他地方拉的代码&#xff0c;把.git文件删除&#xff0c;再重新初始化。 2、提交代码 2.1、提交本地库 2.2、提交远程仓库 2.2.1、创建远程仓库 2.2.2、提交远程仓库–master分支 在本地添加远程仓库&#xff0c;设置别名为origin git remote…

首届教师案例教学竞赛一等奖作品上线至和鲸社区,快来学习!

细心的朋友可能已经发现&#xff0c;近期和鲸社区的频道页上线了一个新专区——“优秀参赛作品专区”。 图.和鲸社区频道页 迄今为止&#xff0c;和鲸参与/支持了 500 多场专业数据科学竞赛&#xff0c;包括面向气象、金融、医学、海洋等不同领域的&#xff0c;面向从业者、科学…

为你的项目加上微信登录(个人开发)

当我们开发个人项目的时候&#xff0c;为了用户登录的便捷性&#xff0c;经常会给我们的项目加上一些除了注册之外的方式&#xff0c;其中最常见的就是微信登录&#xff0c;但作为个人开发者&#xff0c;是无法使用微信的授权登录的&#xff0c;但是通过微信公众号可以获得同样…

【nginx】 实现限流

这里写自定义目录标题 前言正文nginx实现限流并发限制限制单IP并发数量限制单主机服务并发数量 速率限制限流效果 注意疑问参考链接 小结 前言 好久不见&#xff0c;还算为时不晚。最近一个月经历了工作的调整&#xff0c;技术栈从Java转向了Go和Python, 工作显得更忙了些&…

JavaScript基础—for语句、循环嵌套、数组、冒泡排序、综合案例—根据数据生成柱形图

版本说明 当前版本号[20231126]。 版本修改说明20231126初版 目录 文章目录 版本说明目录JavaScript 基础第三天笔记for 语句for语句的基本使用循环嵌套倒三角九九乘法表 数组数组是什么&#xff1f;数组的基本使用定义数组和数组单元访问数组和数组索引数据单元值类型数组长…

测试工程师必学看系列之Jmeter_性能测试:性能测试的流程和术语

性能测试的流程 一、准备工作 1、系统基础功能验证 一般情况下&#xff0c;只有在系统基础功能测试验证完成、系统趋于稳定的情况下&#xff0c;才会进行性能测试&#xff0c;否则性能测试是无意义的。2、测试团队组建 根据该项目的具体情况&#xff0c;组建一个几人的性能测试…

Linux面试题(三)

目录 34、du 和 df 的定义&#xff0c;以及区别&#xff1f; 35、awk 详解。 36、当你需要给命令绑定一个宏或者按键的时候&#xff0c;应该怎么做呢&#xff1f; 37、如果一个 linux 新手想要知道当前系统支持的所有命令的列表&#xff0c;他需要怎么做&#xff1f; 38、…

23年几个能打的UE4游戏技术选型

近期发现很多的精力放在游戏的整体技术选型以及产生的结果上面&#xff0c;所以回顾下几个游戏的选型和结果&#xff1b; 这里一个是自己玩游戏的画面流畅度的直接感受&#xff0c;以及一直非常喜爱的评测“数毛社”&#xff0c;digital foundry&#xff1b; 23年目前来看&…

【NeRF】3、MobileR2L | 移动端实时的神经光场(CVPR2023)

论文&#xff1a;Real-Time Neural Light Field on Mobile Devices 代码&#xff1a;https://github.com/snap-research/MobileR2L 出处&#xff1a;CVPR2023 贡献&#xff1a; 设计了一套移动端实时的 R2L 网络结构 MobileR2L&#xff0c;在 iphone13 上渲染一张 1008x756…

前端学习--React(4)路由

一、认识ReactRouter 一个路径path对应一个组件component&#xff0c;当我们在浏览器中访问一个path&#xff0c;对应的组件会在页面进行渲染 创建路由项目 // 创建项目 npx create router-demo// 安装路由依赖包 npm i react-router-dom// 启动项目 npm run start 简单的路…

【JavaEE】多线程 (2) --线程安全

目录 1. 观察线程不安全 2. 线程安全的概念 3. 线程不安全的原因 4. 解决之前的线程不安全问题 5. synchronized 关键字 - 监视器锁 monitor lock 5.1 synchronized 的特性 5.2 synchronized 使⽤⽰例 1. 观察线程不安全 package thread; public class ThreadDemo19 {p…

LeetCode中链表类题目十条血泪经验总结-全程干货

文章目录 前言干货经验汇总第一梯队第二梯队 力扣代表性链表题目推荐 前言 链表是以节点&#xff08;node&#xff09;存储的链式存储结构&#xff0c;一个node包含一个data域&#xff08;存放数据&#xff09;和一个next域&#xff08;存放下一个node的指针&#xff09;&…

Co-DETR:DETRs与协同混合分配训练论文学习笔记

论文地址&#xff1a;https://arxiv.org/pdf/2211.12860.pdf 代码地址&#xff1a; GitHub - Sense-X/Co-DETR: [ICCV 2023] DETRs with Collaborative Hybrid Assignments Training 摘要 作者提出了一种新的协同混合任务训练方案&#xff0c;即Co-DETR&#xff0c;以从多种标…