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
11 changes: 11 additions & 0 deletions 695/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 695. Max Area of Island
- 前の問題をdfsで解いたのでbfsで解いた(sol1.py)
- `for delta in [1, -1]:`で書くより、diretionsを4つ書き出した方が可読性は高いのかもしれない
- そこだけ書き直した(sol2.py)
- UnionFind
- https://github.com/mamo3gr/arai60/blob/main/695_max-area-of-island/step2.py
- 小さい集合を大きい集合に付け加える
- この場合、adjacentは片側だけで良い
- かなり時間がかかったので、後で解き直したい
- いずれにしても計算量 O(mn) は避けられない

46 changes: 46 additions & 0 deletions 695/sol1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from collections import deque


class Solution:
LAND = 1
WATER = 0

def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
if not grid or not grid[0]:
return 0

def inside_grid(pos):
i, j = pos
return 0 <= i < len(grid) and 0 <= j < len(grid[0])

def generate_adjacent(pos):
i, j = pos
for delta in [1, -1]:
if inside_grid((i + delta, j)):
yield (i + delta, j)
if inside_grid((i, j + delta)):
yield (i, j + delta)

def bfs(pos, visited):
que = deque()
que.append(pos)
visited[pos[0]][pos[1]] = True
area = 0
while que:
curr_pos = que.popleft()
area += 1
for i, j in generate_adjacent(curr_pos):
if grid[i][j] == self.LAND and not visited[i][j]:
visited[i][j] = True
que.append((i, j))
return area

visited = [[False] * len(grid[0]) for _ in range(len(grid))]
area_max = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == self.WATER or visited[i][j]:
continue
area = bfs((i, j), visited)
area_max = max(area, area_max)
return area_max
47 changes: 47 additions & 0 deletions 695/sol2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from collections import deque


class Solution:
LAND = 1
WATER = 0

def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
if not grid or not grid[0]:
return 0
rows, cols = len(grid), len(grid[0])

def generate_if_inside_grid(pos):
i, j = pos
if 0 <= i < rows and 0 <= j < cols:
yield (i, j)

def generate_adjacent(pos):
i, j = pos
yield from generate_if_inside_grid((i + 1, j))
yield from generate_if_inside_grid((i - 1, j))
yield from generate_if_inside_grid((i, j + 1))
yield from generate_if_inside_grid((i, j - 1))

def bfs(pos, visited):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bfs という名前はあまり好まないですが、関数内関数だから少し許容度が高めです。

関数名は、書かれたときには何が返ってくるかが知りたいのであって、要素ではないんですね。
冷蔵庫を断熱膨張などとメカニズムで呼ばれても、クーラーの話をしているかもしれないんです。
https://docs.google.com/document/d/11HV35ADPo9QxJOpJQ24FcZvtvioli770WWdZZDaLOfg/edit?tab=t.0#heading=h.fcs3httrll4l

que = deque()
que.append(pos)
visited[pos[0]][pos[1]] = True
area = 0
while que:
curr_pos = que.popleft()
area += 1
for i, j in generate_adjacent(curr_pos):
if grid[i][j] == self.LAND and not visited[i][j]:
visited[i][j] = True
que.append((i, j))
return area

visited = [[False] * cols for _ in range(rows)]
area_max = 0
for i in range(rows):
for j in range(cols):
if grid[i][j] == self.WATER or visited[i][j]:
continue
area = bfs((i, j), visited)
area_max = max(area, area_max)
return area_max
66 changes: 66 additions & 0 deletions 695/sol3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from typing import List


class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.area = [0] * n

def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]

def add(self, x):
self.area[x] = 1

def union(self, x, y):
root_x = self.find(x)
root_y = self.find(y)
if root_x == root_y:
return
# union by size (area)
if self.area[root_x] < self.area[root_y]:
root_x, root_y = root_y, root_x
self.parent[root_y] = root_x
self.area[root_x] += self.area[root_y]
self.area[root_y] = 0


class Solution:
LAND = 1
WATER = 0

def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
if not grid or not grid[0]:
return 0

rows, cols = len(grid), len(grid[0])

def generate_if_inside_grid(pos):
i, j = pos
if 0 <= i < rows and 0 <= j < cols:
yield (i, j)

def generate_adjacent_one_side(pos):
i, j = pos
yield from generate_if_inside_grid((i + 1, j))
yield from generate_if_inside_grid((i, j + 1))

def idx(i, j):
return i * cols + j

uf = UnionFind(rows * cols)
for i in range(rows):
for j in range(cols):
if grid[i][j] == self.LAND:
uf.add(idx(i, j))

for i in range(rows):
for j in range(cols):
if grid[i][j] == self.WATER:
continue
for i_next, j_next in generate_adjacent_one_side((i, j)):
if grid[i_next][j_next] == self.LAND:
uf.union(idx(i, j), idx(i_next, j_next))
return max(uf.area)