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
39 changes: 39 additions & 0 deletions 200-Number-of-Islands/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 200. Number of Islands

<https://leetcode.com/problems/number-of-islands/>

## step1(まず通す)

以下を繰り返せばいけそう:

- 島を見つける→ 添え字順で見ていく。1があればそれが島の一部として島全体の範囲を確定させにいく
- 島を確定→1のマスに限定した幅優先探索をする。
- カウントアップ

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

`find_whole_island` の中の for ループの前に `seen_nodes.add((row, column))` を書いてたがこれは while の外で1回だけ呼べばいい。

いろいろなチェックを2重ループで呼ぶと定数倍が重いので、最初に全部のノードを「まだ見てない」に詰めて、そこから pop する方がいい?と思ったが比較演算より set にする方が重いので元のままのほうがいいかも。
実際、数人見た範囲では not_seen を用意している人はいなかった

- <https://github.com/naoto-iwase/leetcode/pull/17/changes>
- 自分の実装だと row, column を表す変数名が複数出てきて混乱しやすそうと思っていたが、近傍のマス目を表す変数名として `neighbor` は良いと思った
- ただし今回はスコープも短いので自分の r,c という書き方でも良い気はしている
- <https://github.com/tarinaihitori/leetcode/pull/17/changes>
- 近傍のマス目自体を列挙する代わりに、移動量を列挙して `delta_row/delta_col` とするのもわかりやすい命名
- ただし今回は条件式が長くなりやすいので個人的には近傍を列挙しておいて条件式はシンプルに書きたいと感じた
- 入力を破壊するかどうかの議論がある
- 綺麗に分類できるわけではないと思うが、自分の感覚としては
- 入力に対して何らかの変形を加えた同じ型のものを返す時はどちらでもあり得そう
- e.g. sort() メソッドと sorted()
- 入力に対して何らかの要約を与えるものは、破壊的だとちょっと驚くかも
- 入力について何かを数える、最大値、平均値
- 今回は下だと思っている
- Python の代入は「名前(左辺)をオブジェクト(右辺)に束縛する」(オブジェクトに名前をラベル付けする)ことで、C 言語(やプログラミング一般)を勉強する時によくされる初心者向けの説明「変数という箱に中身を入れる」のメンタルモデルだと間違う
- <https://github.com/huyfififi/coding-challenges/pull/40/changes#r2679381682>
- 添字の範囲外チェックは(x が変数だとして) `x < head or tail <= x` みたいに書くよりは `not (head<= x < tail)` の方が見やすいだろう
- こうするならスッキリするので行と列の判定をまとめて良さそう
- ついでに、すでに見たかチェック→添字の範囲外チェックより逆の方がしっくりくる

## step3(10分以内にさっとかける * 3回)
37 changes: 37 additions & 0 deletions 200-Number-of-Islands/step1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from collections import deque


class Solution:
def numIslands(self, grid: list[list[str]]) -> int:
def find_whole_island(row: int, column: int):
nodes_to_see: deque[tuple[int, int]] = deque([(row, column)])
while nodes_to_see:
node = nodes_to_see.popleft()
seen_nodes.add((row, column))
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 0 <= r < num_rows and 0 <= c < num_columns:
if (r, c) not in seen_nodes and grid[r][c] == "1":
nodes_to_see.append((r, c))
seen_nodes.add((r, c))

num_rows = len(grid)
num_columns = len(grid[0])
seen_nodes: set[tuple[int, int]] = set()
num_islands = 0
for r in range(num_rows):
for c in range(num_columns):
if grid[r][c] == "0":
seen_nodes.add((r, c))
continue
if (r, c) in seen_nodes:
continue

find_whole_island(r, c)
num_islands += 1

return num_islands
41 changes: 41 additions & 0 deletions 200-Number-of-Islands/step2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from collections import deque


class Solution:
def numIslands(self, grid: list[list[str]]) -> int:
def detect_whole_island(row: int, column: int):
nodes_to_see: deque[tuple[int, int]] = deque([(row, column)])
seen_nodes.add((row, column))

@kitano-kazuki kitano-kazuki Jun 28, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

個人的には内部関数で使用する変数は、内部関数の定義前に宣言されて欲しいと思いました。

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.

ありがとうございます。確かに(読む順で)未定義の変数が使われていると読みづらいのでそうしようと思います。

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":
nodes_to_see.append((r, c))
seen_nodes.add((r, c))

num_rows = len(grid)
num_columns = len(grid[0])
seen_nodes: set[tuple[int, int]] = set()
num_islands = 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

detect_whole_island(row, column)
num_islands += 1

return num_islands
41 changes: 41 additions & 0 deletions 200-Number-of-Islands/step3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from collections import deque


class Solution:
def numIslands(self, grid: list[list[str]]) -> int:
def detect_whole_island(row: int, column: int):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

detectというとある島を発見した瞬間みたいな印象を受けるのでexploreの方がいいのではないかと思いました。

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.

なるほど。個人的には explore という過程があってその結果何が分かるのかが表現されている方が好きなんですが、「島全体」というニュアンスはたしかに explore の方がわかりやすいかもしれませんね。

命名の参考にします。

nodes_to_see = deque([(row, column)])
seen_nodes.add((row, column))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

seen_nodesの定義はこの関数の上でもいいのではと思いました。定義されてもない、引数として渡されてもいないものが出てくると若干びっくりするので。

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.

そうですね。関数をインラインで書くにしても変数の宣言・定義の場所は考えた方がよさそうです。ありがとうございますmm

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":
nodes_to_see.append((r, c))
seen_nodes.add((r, c))

num_rows = len(grid)
num_columns = len(grid[0])
seen_nodes: set[tuple[int, int]] = set()
num_islands = 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

detect_whole_island(row, column)
num_islands += 1

return num_islands