LeetCode 733. Flood Fill

An image is represented by an m x n integer grid image where image[i][j] represents the pixel value of the image.

You are also given three integers srsc, and color. You should perform a flood fill on the image starting from the pixel image[sr][sc].

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), and so on. Replace the color of all of the aforementioned pixels with color.

Return the modified image after performing the flood fill.

Example 1:

Input: image = [[1,1,1],[1,1,0],[1,0,1]], sr = 1, sc = 1, color = 2
Output: [[2,2,2],[2,2,0],[2,0,1]]
Explanation: From the center of the image with position (sr, sc) = (1, 1) (i.e., the red pixel), all pixels connected by a path of the same color as the starting pixel (i.e., the blue pixels) 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.

Example 2:

Input: image = [[0,0,0],[0,0,0]], sr = 0, sc = 0, color = 0
Output: [[0,0,0],[0,0,0]]
Explanation: The starting pixel is already colored 0, so no changes are made to the image.

Constraints:

  • m == image.length
  • n == image[i].length
  • 1 <= m, n <= 50
  • 0 <= image[i][j], color < 216
  • 0 <= sr < m
  • 0 <= sc < n

经典的Flood fill,总感觉以前做过但是不知道为啥没有任何记录……大概就是给定一个二维数组中的一个格子,要把跟这个格子相邻且数字相同的格子都变成目标数字。

第一反应就是DFS,写了个helper,先判断一下这个格子的数字一不一样,一样的话就把它的数字改了,然后如果存在上下左右的话就递归调用这个helper就行了。

于是写完代码测试的时候疯狂stack overflow,最后对比了答案才发现是第二个case的问题,应该在主函数里就判断image[sr][sc]的数字和color一不一样,一样就直接返回,不然进了helper就是死循环了。以及看完答案发现自己的代码写的不够简洁美丽。

自己写的:

class Solution {
    public int[][] floodFill(int[][] image, int sr, int sc, int color) {
        if (image[sr][sc] == color) {
            return image;
        }
        fill(image, sr, sc, color, image[sr][sc]);
        return image;
    }

    private void fill(int[][] image, int sr, int sc, int color, int original) {
        if (image[sr][sc] == original) {
            image[sr][sc] = color;
            
            if (sr - 1 >= 0) {
                fill(image, sr - 1, sc, color, original);
            }
            if (sr + 1 < image.length) {
                fill(image, sr + 1, sc, color, original);
            }
            if (sc - 1 >= 0) {
                fill(image, sr, sc - 1, color, original);
            }
            if (sc + 1 < image[0].length) {
                fill(image, sr, sc + 1, color, original);
            }
        }
    }
}

简洁美丽的:

class Solution {
    public int[][] floodFill(int[][] image, int sr, int sc, int color) {
        if (image[sr][sc] == color) {
            return image;
        }
        fill(image, sr, sc, color, image[sr][sc]);
        return image;
    }

    private void fill(int[][] image, int sr, int sc, int color, int original) {
        if (sr < 0 || sr >= image.length || sc < 0 || sc >= image[0].length || image[sr][sc] != original) {
            return;
        }
        image[sr][sc] = color;
        fill(image, sr + 1, sc, color, original);
        fill(image, sr - 1, sc, color, original);
        fill(image, sr, sc + 1, color, original);
        fill(image, sr, sc - 1, color, original);
    }
}

看到有人解释DFS解释的非常到位。通常都需要用到visited数组来表示这个格子有没有被visited,但是这题因为改了color所以就可以省略这个visited数组啦。LeetCode - The World's Leading Online Programming Learning Platform

然后还看到了有人用BFS来做,以及提出了DFS可以不用强行写四个fill,直接用一个DIR数组,每次取相邻的两个代表往哪边移动:

int[] DIRS = {0, 1, 0, -1, 0};

LeetCode - The World's Leading Online Programming Learning Platform

 BFS其实和普通的bfs差不多,也是用一个queue,queue里存的是坐标。先开始往里放image[sr][sc],然后while queue is not empty的时候每次取queue front拿出来坐标,然后就跟dfs是一样的判断,接着dfs里是递归调用helper,这里就是重复把新的坐标加入queue。

自己写的时候蠢到最后加queue的时候用了sr sc而不是新拿到的r c……debug了巨久print出来才发现每次用的坐标都一样……

class Solution {
    public int[][] floodFill(int[][] image, int sr, int sc, int color) {
        if (image[sr][sc] == color) {
            return image;
        }
        int original = image[sr][sc];
        Queue<int[]> queue = new LinkedList<>();
        queue.add(new int[]{sr, sc});
        while (!queue.isEmpty()) {
            int[] pixel = queue.remove();
            int r = pixel[0];
            int c = pixel[1];
            if (r < 0 || r >= image.length || c < 0 || c >= image[0].length || image[r][c] != original) {
                continue;
            }
            image[r][c] = color;
            queue.add(new int[]{r - 1, c});
            queue.add(new int[]{r + 1, c});
            queue.add(new int[]{r, c - 1});
            queue.add(new int[]{r, c + 1});
        }
        return image;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值