-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathflood-fill.py
More file actions
122 lines (98 loc) · 4.18 KB
/
flood-fill.py
File metadata and controls
122 lines (98 loc) · 4.18 KB
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# https://leetcode.com/problems/flood-fill/
# Related Topics: BFS, DFS
# Difficulty: Easy
# same BFS solution as further below but a little bit more clean
class Solution:
# Time complexity: O(n * m) where n and m are the rows and columns of the matrix
# Space complexity: O(n * m)
# BFS
def floodFill(self, image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
R, C = len(image), len(image[0])
start_color = image[sr][sc]
if start_color == newColor: return image
deq = deque([(sr, sc)])
image[sr][sc] = newColor
while deq:
r, c = deq.popleft()
for dr, dc in ((-1, 0), (0, 1), (1, 0), (0, -1)):
nr, nc = r+dr, c+dc
if 0 <= nr < R and 0 <= nc < C and image[nr][nc] == start_color:
deq.append((nr, nc))
image[nr][nc] = newColor
return image
# Initial thoughts:
# Starting with the initial pixel we can approach the problem in a BFS manner.
# Change the first pixel and enqueue its 4-directionally adjacent pixels if they
# comply with the criterion of having the old color and are in bounds with regards
# to the original pixel.
# Time complexity: O(n) where n === number of elements in image
# Space complexity: O(n) where n === number of leements in image
from collections import deque
from typing import List
class Solution2:
def floodFill(self, image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
R, C = len(image), len(image[0])
currPixels = [(sr, sc)]
oldColor = image[currPixels[0]][currPixels[1]]
if oldColor == newColor:
return image
newPixels = []
while len(currPixels) > 0:
r, c = currPixels.pop()
image[r][c] = newColor
if r > 0 and image[r-1][c] == oldColor:
newPixels.append((r-1, c))
if c+1 < C and image[r][c+1] == oldColor:
newPixels.append((r, c+1))
if r+1 < R and image[r+1][c] == oldColor:
newPixels.append((r+1, c))
if c > 0 and image[r][c-1] == oldColor:
newPixels.append((r, c-1))
if len(currPixels == 0):
currPixels = newPixels
newPixels = []
return image
# Same solution as above (using BFS), but using a real queue for BFS
class Solution:
def floodFill(self, image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
R, C = len(image), len(image[0])
oldColor = image[sr][sc]
if oldColor == newColor:
return image
currPixels = deque()
currPixels.append((sr, sc))
while len(currPixels) > 0:
r, c = currPixels.popleft()
image[r][c] = newColor
if r > 0 and image[r-1][c] == oldColor:
currPixels.append((r-1, c))
if c+1 < C and image[r][c+1] == oldColor:
currPixels.append((r, c+1))
if r+1 < R and image[r+1][c] == oldColor:
currPixels.append((r+1, c))
if c > 0 and image[r][c-1] == oldColor:
currPixels.append((r, c-1))
return image
# Using a DFS approach.
# Time and space complexities don't change in comparison to BFS.
# This approach is arguable more elegant, readable, but IMHO
# it "looks" less like a flood fill and if investigating, simulating
# or depicting of a flood fill was in order, DFS couldn't do it.
class Solution:
def floodFill(self, image: List[List[int]], sr: int, sc: int, newColor: int) -> List[List[int]]:
R, C = len(image), len(image[0])
oldColor = image[sr][sc]
if oldColor == newColor:
return image
def dfs(r: int, c: int) -> None:
image[r][c] = newColor
if r > 0 and image[r-1][c] == oldColor:
dfs(r-1, c)
if c+1 < C and image[r][c+1] == oldColor:
dfs(r, c+1)
if r+1 < R and image[r+1][c] == oldColor:
dfs(r+1, c)
if c > 0 and image[r][c-1] == oldColor:
dfs(r, c-1)
dfs(sr, sc)
return image