代码改变世界

[LeetCode] 733. Flood Fill_Easy tag: BFS

2018-07-02 11:05  Johnson_强生仔仔  阅读(327)  评论(0编辑  收藏  举报

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].

 

因为是2D-array的题目, 然后上下左右4个方向, 跟相对位置有关, 那么实际上跟distinct island很像, 那么很基础的做法, BFS. 此时要注意的是, 如果用BFS, 那么很有可能你的邻居后面可能再次找你, 所以记住, 要用BFS的时候, 判断需不需要加入visited 这样一个set来避免重复的判断某一个元素, 甚至无法跳出BFS的循环. 

所以按照hiredintech上面的canvas的步骤, 一步一步来, 

1. constraints:

      1) image 的size给定了, 至少不用判断image的行或者列可能为空的情况.

      2) 每个pixel的值给定了i,并且newcolor的值也给定 [0, 65535], 所以不用判断newcolor的范围.

      3) image的max size给定了, 最大[50]*[50]

      4) sr跟sc 默认为有效值, 很好, 不用判断了.

 

2. Ideas:

    BFS:   assum m*n array

              T:  O(m*n)   因为要扫到array的每一个元素

    S: O(m*n)  因为queue可能最多把整个array都append进去.

    1) edge case, newcolor == oricolor, 直接返回原array

     2) queue, 初始化将(sr,sc) 放入

     3) 如果queue非空, popleft, 然后ans[nr][nc] = newcolor, visited.add(nr, nc)

     4) 然后判断4个directions, 另外注意还要判断是否已经visited过了.

     3) 如果邻居有效, 并且color == oricolor, 没有visited过, queue.append(邻居)

     4) 返回 ans

 Update on 03/06/2021:  init visited with (sr, sc) , and put (nr,nc) in visited once append it into queue to avoid duplicates. 

 

3. code:

 1 class Solution:
 2     def floodfill(self, image, sr, sc, newColor):
 3         lr, lc, oricolor, ans = len(image), len(image[0]), image[sr][sc], image
 4         if oricolor == newColor: return ans
 5         queue, visited, dirs = collections.deque([(sr, sc)]), set([(sr, sc)]), [(0,1), (0, -1), (1, 0), (-1, 0)]
 6         while queue:
 7             pr, pc = queue.popleft()
 8             ans[pr][pc] = newColor
 9             # visited.add((pr, pc))
10             for d1, d2 in dirs:
11                 nr, nc = pr + d1, pc + d2
12                 if 0 <= nr < lr and 0 <= nc < lc and image[nr][nc] == oricolor and (nr, nc) not in visited:
13                     queue.append((nr, nc))
             visited.add((nr, nc)) # put add method here instead to avoid duplicates
14 return ans

 

4. test cases:

1. newcolor == oricolor

2. 

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]]