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
29 changes: 29 additions & 0 deletions 695-Max-Area-of-Island/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# 695. Max Area of Island

<https://leetcode.com/problems/max-area-of-island/>

## step1(まず通す)

直前に解いた <https://leetcode.com/problems/number-of-islands/> とほぼ同じ。数える対象が違うだけ。

<https://leetcode.com/problems/number-of-islands/> では str の "0" or "1", こっちは int の 0 or 1 で海と陸が表現されているが、ゲームのマップとか地図データの処理とかそういうのを考えるといろんな地形をわかりやすい形で表現したいので [enum](https://docs.python.org/ja/3/library/enum.html) で管理したい。

(row, column) も、大規模なコードベースなら tuple[int,int] に Position とか名前をつけておきたいかも。

## step2(整形&他の人のコードを読む)

- <https://github.com/shintaro1993/arai60/pull/22/changes>
- やはり 0/1 だとわかりづらいので、この方は `WATER = 0` のように定数としておいている
- <https://github.com/naoto-iwase/leetcode/pull/18#discussion_r2424179923>
- area のインクリメントをキューへの追加時にするのか取り出し時にするのか
- 今回の自分のコードは、同じマスを2回キューに詰めないようにキューへ詰めたタイミングで seen への追加を行っており、area のインクリメントも同じところにまとめている

- <https://github.com/naoto-iwase/leetcode/pull/18#discussion_r2425068670>
- itertools.product を使うと単純なn重ループのネストを浅くできる

enum を使う場合、int として比較したいので [IntEnum](https://docs.python.org/ja/3/library/enum.html#enum.IntEnum) を使う。そうすると、作成する maxAreaOfIsland の引数 grid の型も `list[list[NodeType]]` が良さそう。

## step3(10分以内にさっとかける * 3回)

- <https://github.com/MA-yo-TA/leetcode/pull/18#discussion_r3487683841>
- やってる最中に一つ前の問題のレビューをいただいたので反映させた
45 changes: 45 additions & 0 deletions 695-Max-Area-of-Island/step1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from collections import deque


class Solution:
def maxAreaOfIsland(self, grid: list[list[int]]) -> int:
def get_area_of_island(row: int, column: int) -> int:
nodes_to_see = deque([(row, column)])
seen_nodes.add((row, column))
area = 1
while nodes_to_see:
node = nodes_to_see.popleft()
for r, c in (
(node[0], node[1] - 1),
(node[0], node[1] + 1),
(node[0] - 1, node[1]),
(node[0] + 1, node[1]),
):
if not (0 <= r < num_rows and 0 <= c < num_columns):
continue
if (r, c) in seen_nodes:
continue

if grid[r][c] == 1:
area += 1
nodes_to_see.append((r, c))
seen_nodes.add((r, c))

return area

num_rows = len(grid)
num_columns = len(grid[0])
seen_nodes: set[tuple[int, int]] = set()
max_area_of_island = 0
for row in range(num_rows):
for column in range(num_columns):
if (row, column) in seen_nodes:
continue
if grid[row][column] == 0:
seen_nodes.add((row, column))
continue

area = get_area_of_island(row, column)
max_area_of_island = max(area, max_area_of_island)

return max_area_of_island
51 changes: 51 additions & 0 deletions 695-Max-Area-of-Island/step2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from collections import deque
from enum import IntEnum
from itertools import product


class NodeType(IntEnum):
WATER = 0
LAND = 1


class Solution:
def maxAreaOfIsland(self, grid: list[list[NodeType]]) -> int:
def get_area_of_island(row: int, column: int) -> int:
nodes_to_see = deque([(row, column)])
seen_nodes.add((row, column))
area = 1
while nodes_to_see:
node = nodes_to_see.popleft()
for r, c in (
(node[0], node[1] - 1),
(node[0], node[1] + 1),
(node[0] - 1, node[1]),
(node[0] + 1, node[1]),
):
if not (0 <= r < num_rows and 0 <= c < num_columns):
continue
if (r, c) in seen_nodes:
continue

if grid[r][c] == NodeType.LAND:
area += 1
nodes_to_see.append((r, c))
seen_nodes.add((r, c))

return area

num_rows = len(grid)
num_columns = len(grid[0])
seen_nodes: set[tuple[int, int]] = set()
max_area_of_island = 0
for row, column in product(range(num_rows), range(num_columns)):
if (row, column) in seen_nodes:
continue
if grid[row][column] == NodeType.WATER:
seen_nodes.add((row, column))
continue

area = get_area_of_island(row, column)
max_area_of_island = max(area, max_area_of_island)

return max_area_of_island
52 changes: 52 additions & 0 deletions 695-Max-Area-of-Island/step3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from collections import deque
from enum import IntEnum
from itertools import product


class NodeType(IntEnum):
WATER = 0
LAND = 1


class Solution:
def maxAreaOfIsland(self, grid: list[list[NodeType]]) -> int:
num_rows = len(grid)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ただの感想ですが、こうして、変数の使用より宣言が先の行にあると見やすいです。

num_columns = len(grid[0])
seen_nodes: set[tuple[int, int]] = set()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

単語nodeを変数名に使っていますが、個人的には、cell, position, coordinateあたりの単語のほうが見慣れていて、引っかかりを感じにくいです。
ノードと言われたときは、このコードはBFSをしていて、そのノードは(row, column)だ、と考える必要があるからだと思います。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

ありがとうございます。おっしゃる通り cell とかの方がいいですね。

node はグラフ的な頭に引っ張られた命名になっちゃってますね。


def get_area_of_island(row: int, column: int) -> int:
nodes_to_see = deque([(row, column)])
seen_nodes.add((row, column))
area = 1
while nodes_to_see:
node = nodes_to_see.popleft()
for r, c in (
(node[0], node[1] - 1),
(node[0], node[1] + 1),
(node[0] - 1, node[1]),
(node[0] + 1, node[1]),
):
if not (0 <= r < num_rows and 0 <= c < num_columns):
continue
if (r, c) in seen_nodes:
continue

if grid[r][c] == NodeType.LAND:
area += 1
nodes_to_see.append((r, c))
seen_nodes.add((r, c))

return area

max_area_of_island = 0
for row, column in product(range(num_rows), range(num_columns)):
if (row, column) in seen_nodes:
continue
if grid[row][column] == NodeType.WATER:
seen_nodes.add((row, column))
continue

area = get_area_of_island(row, column)
max_area_of_island = max(area, max_area_of_island)

return max_area_of_island