我爱学算法之——floodfill算法(上)

前言

Flood Fill(也称为种子填充算法)是一种用于确定连接到多维数组中给定节点的区域的算法

核心思想

  • 从起点开始:从一个初始像素(种子点)开始
  • 扩散填充:向四周(通常为4方向或8方向)扩展
  • 条件匹配:只填充与种子点颜色相同且相邻的像素
  • 避免重复:标记已访问的位置,防止重复处理

一、图像渲染

题目解析

给定一个 m*n 的二维数组,从起始位置 [sr,sc] 开始,将从起始位置的 上下左右 四个方向上 相邻且与起始位置初始颜色相同的像素点进行染色,直到没有其他原始颜色的相邻像素。

算法思路

这道题整体还是非常简单的,从起始位置开始,进行一次深度优先遍历 DFS 即可。

注意 :当起始位置[sr, sc]的颜色和目标颜色 color 相同时,直接返回原二维数组即可。

代码实现

cpp 复制代码
class Solution {
    int dx[4] = {-1, 1, 0, 0};
    int dy[4] = {0, 0, -1, 1};

public:
    void dfs(vector<vector<int>>& image, int i, int j, int srcColor,
             int destColor) {
        // 变色
        int m = image.size();
        int n = image[0].size();
        image[i][j] = destColor;
        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 && image[x][y] == srcColor)
                dfs(image, x, y, srcColor, destColor);
        }
    }
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc,
                                  int color) {
        if (image[sr][sc] != color)
            dfs(image, sr, sc, image[sr][sc], color);
        return image;
    }
};

二、岛屿数量

题目解析

给定一个n*m的二维数组,其中1表示陆地、0表示海洋;

多个相邻的陆地可以看做是一座岛屿,要求计算网格中岛屿的数量

算法思路

遍历grid数组,遍历到陆地(1)并且该陆地没有和其他陆地形成岛屿(没有被BFS/DFS遍历过),就从该节点进行一次BFS/DFS遍历。

这样我们只需要统计在遍历grid时,进行BFS/DFS的次数即可。

这里使用 DFS 来接解决这道题

代码实现

cpp 复制代码
class Solution {
    int dx[4] = {-1, 1, 0, 0};
    int dy[4] = {0, 0, -1, 1};
    bool vis[300][300];

public:
    void dfs(vector<vector<char>>& grid, int i, int j) {
        vis[i][j] = true;
        int m = grid.size(), n = grid[0].size();
        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);
        }
    }
    int numIslands(vector<vector<char>>& grid) {
        int m = grid.size();
        int 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]) {
                    dfs(grid, i, j);
                    ret++;
                }
            }
        }
        return ret;
    }
};

三、岛屿的最大面积

题目解析

算法思路

这道题的结题思路也是和求岛屿数量大同小异;

还是遍历grid数组,在遍历到陆地并且该陆地没有和其他陆地组成岛屿。(遍历到1并且该位置没有被遍历过)

就从该位置进行一次BFS遍历(DFS也可以解决),并求出岛屿的面积;

然后统计岛屿面积的最大值 然后返回即可。

代码实现

cpp 复制代码
class Solution {
    int dx[4] = {-1, 1, 0, 0};
    int dy[4] = {0, 0, -1, 1};
    bool vis[50][50];

public:
    void dfs(vector<vector<int>>& grid, int i, int j, int& cnt) {
        ++cnt;
        vis[i][j] = true;
        int m = grid.size();
        int n = grid[0].size();
        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, cnt);
        }
    }
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int ret = 0, cnt = 0;
        int 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]) {
                    dfs(grid, i, j, cnt);
                    ret = max(ret, cnt);
                    cnt = 0;
                }
            }
        }
        return ret;
    }
};

四、被围绕的区域

题目解析

算法思路

将所有不在边缘区域的 O 全部修改成 X

  • 先将在边缘的 O 区域进行标记(特殊处理,修改成其他无关字符)
  • 再将所有没有标记的 O 全部修改成 X
  • 最后,再复原边缘区域的 O

代码实现

cpp 复制代码
class Solution {
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    bool vis[210][210];

public:
    void dfs(vector<vector<char>>& board, int i, int j, bool isChange = false) {
        if (isChange)
            board[i][j] = 'X';
        vis[i][j] = true;
        int m = board.size();
        int n = board[0].size();
        for (int k = 0; k < 4; k++) {
            int x = i + dx[k];
            int y = j + dy[k];
            if (x >= 0 && y >= 0 && x < m && y < n && !vis[x][y] &&
                board[x][y] == 'O')
                dfs(board, x, y, isChange);
        }
    }
    void solve(vector<vector<char>>& board) {
        // 处理边界
        int m = board.size(), n = board[0].size();
        for (int i = 0; i < m; i++) {
            if (board[i][0] == 'O' && !vis[i][0])
                dfs(board, i, 0);
            if (board[i][n - 1] == 'O' && !vis[i][n - 1])
                dfs(board, i, n - 1);
        }
        for (int i = 0; i < n; i++) {
            if (board[0][i] == 'O' && !vis[0][i])
                dfs(board, 0, i);
            if (board[m - 1][i] == 'O' && !vis[m - 1][i])
                dfs(board, m - 1, i);
        }
        // 修改内部
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (board[i][j] == 'O' && !vis[i][j])
                    dfs(board, i, j, true);
            }
        }
    }
};

本篇文章到这里就结束了,感谢支持

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

相关推荐
wuweijianlove1 小时前
算法性能的渐近与非渐近行为对比的技术4
算法
_dindong1 小时前
cf1091div2 C.Grid Covering(数论)
c++·算法
AI成长日志1 小时前
【Agentic RL】1.1 什么是Agentic RL:从传统RL到智能体学习
人工智能·学习·算法
黎阳之光2 小时前
黎阳之光:视频孪生领跑者,铸就中国数字科技全球竞争力
大数据·人工智能·算法·安全·数字孪生
skywalker_112 小时前
力扣hot100-3(最长连续序列),4(移动零)
数据结构·算法·leetcode
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 17. 电话号码的字母组合 | C++ 回溯算法经典模板
c++·算法·leetcode
_李小白2 小时前
【OSG学习笔记】Day 38: TextureVisitor(纹理访问器)
android·笔记·学习
wfbcg3 小时前
每日算法练习:LeetCode 209. 长度最小的子数组 ✅
算法·leetcode·职场和发展
_日拱一卒3 小时前
LeetCode:除了自身以外数组的乘积
数据结构·算法·leetcode
计算机安禾3 小时前
【数据结构与算法】第36篇:排序大总结:稳定性、时间复杂度与适用场景
c语言·数据结构·c++·算法·链表·线性回归·visual studio