我爱学算法之——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

相关推荐
booksyhay2 小时前
XCP学习笔记(2)-指令详解
笔记·学习
tankeven2 小时前
HJ136 翻之
c++·算法
robch3 小时前
golang container/heap 是一个为任意类型实现堆(优先队列)接口的包
数据结构·算法·golang
96773 小时前
力扣面试经典150 88. 合并两个有序数组 归并排序的merge函数
算法·leetcode·面试
菜鸡儿齐5 小时前
Unsafe方法学习
java·python·学习
留白_10 小时前
MySQL学习(7)——存储过程
学习
放下华子我只抽RuiKe510 小时前
算法的试金石:模型训练、评估与调优的艺术
人工智能·深度学习·算法·机器学习·自然语言处理·数据挖掘·线性回归
oem11010 小时前
C++中的享元模式实战
开发语言·c++·算法
流云鹤10 小时前
每日一题0316
算法