The Image Flood Fill Algorithm (C++)

  • 时间:2020-10-11 15:48:46
  • 分类:网络文摘
  • 阅读:90 次

An image is represented by a 2-D array of integers, each integer representing the pixel value of the image (from 0 to 65535). Given a coordinate (sr, sc) representing the starting pixel (row and column) of the flood fill, and a pixel value newColor, “flood fill” the image.

To perform a “flood fill”, consider the starting pixel, plus any pixels connected 4-directionally to the starting pixel of the same color as the starting pixel, plus any pixels connected 4-directionally to those pixels (also with the same color as the starting pixel), and so on. Replace the color of all of the aforementioned pixels with the newColor.

At the end, return the modified image.

Example 1:
Input:
image = [[1,1,1],[1,1,0],[1,0,1]]
sr = 1, sc = 1, newColor = 2

Output: [[2,2,2],[2,2,0],[2,0,1]]

Explanation:

  • From the center of the image (with position (sr, sc) = (1, 1)), all pixels connected.
  • by a path of the same color as the starting pixel are colored with the new color.
  • Note the bottom corner is not colored 2, because it is not 4-directionally connected to the starting pixel.

Note:

  • The length of image and image[0] will be in the range [1, 50].
  • The given starting pixel will satisfy 0 < = sr < image.length and 0 <= sc < image[0].length.
  • The value of each color in image[i][j] and newColor will be an integer in [0, 65535].

Recursion Flood Fill – Depth First Search

The flood fill algorithm can be done via recursion using the DPS (Depth First Search Algorithm). We can modify the original image in order to mark a pixel that has been flooded. Along the four directions, if the pixel is the same as the origin color, we set it to the target.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
        int height = image.size();
        if (height == 0) return image;
        int width = image[0].size();
        if (width == 0) return image;
        int color = image[sr][sc];
        if (color == newColor) return image;
        image[sr][sc] = newColor;
        if ((sr > 0) && (image[sr - 1][sc] == color)) floodFill(image, sr - 1, sc, newColor);
        if ((sc > 0) && (image[sr][sc - 1] == color)) floodFill(image, sr, sc - 1, newColor);
        if ((sr < height - 1)  && (image[sr + 1][sc] == color)) floodFill(image, sr + 1, sc, newColor);
        if ((sc < width - 1) && (image[sr][sc + 1] == color)) floodFill(image, sr, sc + 1, newColor);
        return image;
    }
};
class Solution {
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
        int height = image.size();
        if (height == 0) return image;
        int width = image[0].size();
        if (width == 0) return image;
        int color = image[sr][sc];
        if (color == newColor) return image;
        image[sr][sc] = newColor;
        if ((sr > 0) && (image[sr - 1][sc] == color)) floodFill(image, sr - 1, sc, newColor);
        if ((sc > 0) && (image[sr][sc - 1] == color)) floodFill(image, sr, sc - 1, newColor);
        if ((sr < height - 1)  && (image[sr + 1][sc] == color)) floodFill(image, sr + 1, sc, newColor);
        if ((sc < width - 1) && (image[sr][sc + 1] == color)) floodFill(image, sr, sc + 1, newColor);
        return image;
    }
};

However, the above implementation may still produce stack over flow if the recursion depths is large.

Flood Fill Algorithm with Breadth First Search

We can solve the problem of stack-over-flow by using BFS (Breadth First Search). We maintain a queue with initial node of the start pixel. Every iteration, we de-queue and push possible four directions into the queue.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
        int height = image.size();
        if (height == 0) return image;
        int width = image[0].size();
        if (width == 0) return image;
        int color = image[sr][sc];
        if (color == newColor) return image;
        queue<pair<int, int>> Q;
        Q.push(make_pair(sr, sc));
        while (Q.size() > 0) {
            auto p = Q.front();
            Q.pop();
            int r = p.first;
            int c = p.second;
            image[r][c] = newColor;
            if ((r < height - 1) && (image[r + 1][c] == color)) {
                Q.push(make_pair(r + 1, c));
            }
            if ((r > 0) && (image[r - 1][c] == color)) {
                Q.push(make_pair(r - 1, c));
            }
            if ((c < width - 1) && (image[r][c + 1] == color)) {
                Q.push(make_pair(r, c + 1));
            }
            if ((c > 0) && (image[r][c - 1] == color)) {
                Q.push(make_pair(r, c - 1));
            }        
        }
        return image;
    }
};
class Solution {
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
        int height = image.size();
        if (height == 0) return image;
        int width = image[0].size();
        if (width == 0) return image;
        int color = image[sr][sc];
        if (color == newColor) return image;
        queue<pair<int, int>> Q;
        Q.push(make_pair(sr, sc));
        while (Q.size() > 0) {
            auto p = Q.front();
            Q.pop();
            int r = p.first;
            int c = p.second;
            image[r][c] = newColor;
            if ((r < height - 1) && (image[r + 1][c] == color)) {
                Q.push(make_pair(r + 1, c));
            }
            if ((r > 0) && (image[r - 1][c] == color)) {
                Q.push(make_pair(r - 1, c));
            }
            if ((c < width - 1) && (image[r][c + 1] == color)) {
                Q.push(make_pair(r, c + 1));
            }
            if ((c > 0) && (image[r][c - 1] == color)) {
                Q.push(make_pair(r, c - 1));
            }        
        }
        return image;
    }
};

As the queue can dynamically grow or shrink, there is no risks of overflowing the stack.

–EOF (The Ultimate Computing & Technology Blog) —

推荐阅读:
夏季凉拌西红柿时用蜂蜜更滋补  对大豆制品存在的一些认识误区  食品安全:广州镉超标大米事件追踪  味精的食用安全性及合适用量问题  食品安全问题并不是食品添加剂的错  温州苍南黑作坊两年产千吨剧毒湿米面  食药监总局提醒注意保健食品五大陷阱  对儿童健康成长有益的六大食物  健康养生:七种常见的黑色滋补食物  竹炭食品排毒就是一个忽悠人的概念 
评论列表
添加评论