Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions 0733.Flood-Fill/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 733. Flood Fill

## step1
in-placeだが良いだろう

DFS

## step2

他の人のコード

https://github.com/huyfififi/coding-challenges/pull/9

- キュー/スタックに入れる前に色を塗る/範囲を先に見ることで重複探索を防ぐ(DFS で「呼び出し後に塗る」と無限再帰になりうる)

https://github.com/ryosuketc/leetcode_grind75/pull/9

https://github.com/Kitaken0107/GrindEasy/pull/12


同じBFS/DFSでもキューに入れる前に条件で省くか、とりあえず入れておくかの二通りがある。

個人的には無駄な操作を省く前者の方が好み

読みやすさ的には後者を好む人もいそう






> 3回passするようになると、コードがちょうどいい抽象度で頭に収まるような実感がある。

サボっているので真面目にやるべきなのか...

seenが不要なのでその点を改良する

## step3

個人的に馴染みのない、BFS+とりあえず入れておく解法を書く
28 changes: 28 additions & 0 deletions 0733.Flood-Fill/step1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class Solution:
def floodFill(
self, image: List[List[int]], sr: int, sc: int, color: int
) -> List[List[int]]:
base_color = image[sr][sc]
seen = [[False] * len(image[0]) for _ in range(len(image))]
stack = [(sr, sc)]
seen[sr][sc] = True

while stack:
row, col = stack.pop()
image[row][col] = color
for row_next, col_next in (
(row, col + 1),
(row, col - 1),
(row + 1, col),
(row - 1, col),
):
if not (0 <= row_next < len(image) and 0 <= col_next < len(image[0])):
continue
if (
not seen[row_next][col_next]
and image[row_next][col_next] == base_color
):
stack.append((row_next, col_next))
seen[row_next][col_next] = True

return image
95 changes: 95 additions & 0 deletions 0733.Flood-Fill/step2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import collections


class Solution:
def floodFill(
self, image: List[List[int]], sr: int, sc: int, color: int
) -> List[List[int]]:
"""BFS: 四方向はとりあえず全部キューに入れ、取り出したあと境界と元色を見る。"""
base_color = image[sr][sc]
if base_color == color:
return image

num_rows = len(image)
num_cols = len(image[0])
frontier = collections.deque([(sr, sc)])

while frontier:
row, col = frontier.popleft()
if not (0 <= row < num_rows and 0 <= col < num_cols):
continue
if image[row][col] != base_color:
continue
image[row][col] = color
frontier.append((row - 1, col))
frontier.append((row + 1, col))
frontier.append((row, col - 1))
frontier.append((row, col + 1))

return image


class Solution:
def floodFill(
self, image: List[List[int]], sr: int, sc: int, color: int
) -> List[List[int]]:
"""BFS(deque)、キューに多重投入されても、取り出し時に base_color でないマスは skip。"""
base_color = image[sr][sc]
if base_color == color:
return image

num_rows = len(image)
num_cols = len(image[0])
directions = (
(-1, 0),
(1, 0),
(0, -1),
(0, 1),
)
frontier = collections.deque([(sr, sc)])

while frontier:
row, col = frontier.popleft()
if image[row][col] != base_color:
continue
image[row][col] = color
for dr, dc in directions:
row_next, col_next = row + dr, col + dc
if (
0 <= row_next < num_rows
and 0 <= col_next < num_cols
and image[row_next][col_next] == base_color
):
frontier.append((row_next, col_next))

return image


class Solution:
def floodFill(
self, image: List[List[int]], sr: int, sc: int, color: int
) -> List[List[int]]:
"""DFS 再帰"""
base_color = image[sr][sc]
if base_color == color:
return image

num_rows = len(image)
num_cols = len(image[0])

def paint_region(row: int, col: int) -> None:
if not (0 <= row < num_rows and 0 <= col < num_cols):
return
if image[row][col] != base_color:
return
image[row][col] = color
for dr, dc in (
(-1, 0),
(1, 0),
(0, -1),
(0, 1),
):
paint_region(row + dr, col + dc)

paint_region(sr, sc)
return image
30 changes: 30 additions & 0 deletions 0733.Flood-Fill/step3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import collections


class Solution:
def floodFill(
self, image: List[List[int]], sr: int, sc: int, color: int
) -> List[List[int]]:
color_to_update = image[sr][sc]
if color_to_update == color:
return image

frontier = collections.deque([(sr, sc)])

while frontier:
row, col = frontier.popleft()
if not (0 <= row < len(image) and 0 <= col < len(image[0])):
continue
if image[row][col] != color_to_update:
continue
image[row][col] = color

for next_row, next_col in (
(row, col + 1),
(row, col - 1),
(row + 1, col),
(row - 1, col),
):
frontier.append((next_row, next_col))

return image