-
Notifications
You must be signed in to change notification settings - Fork 0
200. Number of Islands #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| ## 考察 | ||
| - 何回か解いたことあり | ||
| - つまり、抽象化すると陸をノードとするグラフの連結成分の数を求めればOK | ||
| - 方針 | ||
| - DFS | ||
| - BFS | ||
| - Union Find | ||
| - 昔この問題をUnion Findでやってみたことがあるが、あまり綺麗に書けなかった記憶 | ||
| - 常識の範囲内に入っているか気になる | ||
| - まずは一番実装しやすいDFSでやる | ||
| - あとは実装 | ||
|
|
||
| ## Step1 | ||
| - DFSで実装した | ||
| - time: O(mn), space: O(mn) | ||
| - 気になった点 | ||
| - 関数内に関数を書く書き方をよく使っているけど、これ大丈夫? | ||
| - 実務ではこの書き方使ったことない | ||
|
|
||
| ## Step2 | ||
| - 他の人のPRを検索 | ||
| - dfsという名前は使わないように | ||
| - よくない癖が付いてた。。 | ||
| - Ref. https://discord.com/channels/1084280443945353267/1231966485610758196/1236231890038689844 | ||
| - 元のgridを破壊的に変更して陸を沈めていく方法もあるのか | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. deepcopy する手もあります。入力を破壊していいかと、出力を破壊されていいかは気にしておきましょう。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 訪問済みを管理する方法についてはたくさんの議論があるので、全部選択肢としてぱっと出るようにしておきます。 |
||
| - メモリは抑えられるが、バグりそう | ||
| - Ref. https://github.com/hayashi-ay/leetcode/pull/33/files#r1648958531 | ||
| - LANDとWATERはenum的に定義しておくと可読性良さそう | ||
| - Pythonのenumはパフォーマンスが悪いみたいなのをどっかで見た気がする | ||
| - でもまあそれがボトルネックになることは考えられない | ||
| - ここでは定数として定義しておくのが良さそう | ||
| - Ref. https://github.com/hayashi-ay/leetcode/pull/33/files#diff-225d97de8f43ab6e115258cc7d483e5a343d8556774b2dde47c392b38b49e89bR37 | ||
| - 関数内に関数を書くのはとくにコメント付いてないので大丈夫そう | ||
| - Union Find実装もある | ||
| - Ref. https://github.com/hayashi-ay/leetcode/pull/33/files#diff-225d97de8f43ab6e115258cc7d483e5a343d8556774b2dde47c392b38b49e89bR98 | ||
| - あとはBFSでもやってみる | ||
| - `step2.py` へ追加 | ||
|
|
||
| ## Step3 | ||
| - 1回目: 5m37s | ||
| - 2回目: 5m12s | ||
| - 3回目: 4m51s | ||
|
|
||
| ## Step4 | ||
| - レビューを元に修正 | ||
| - 変数名の見直し | ||
| - n_row -> num_rows | ||
| - n_col -> num_cols | ||
| - drow -> delta_row | ||
| - dcol -> delta_col | ||
| - explore_islandの引数にtupleを渡すのではなく、intを2つ渡すようにした | ||
| - 方向を行と列で分けて書いていたけど、ペアにしてみた | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| class Solution: | ||
| def numIslands(self, grid: List[List[str]]) -> int: | ||
| m = len(grid) | ||
| n = len(grid[0]) | ||
| visited = [[False] * n for _ in range(m)] | ||
|
|
||
| def dfs(node: tuple): | ||
| current_row, current_col = node | ||
| visited[current_row][current_col] = True | ||
|
|
||
| for next_node in get_neighbors(node): | ||
| next_row, next_col = next_node | ||
| if not visited[next_row][next_col]: | ||
| dfs(next_node) | ||
|
|
||
| def get_neighbors(node: tuple): | ||
| drow = (0, 1, 0, -1) | ||
| dcol = (1, 0, -1, 0) | ||
| neighbors = [] | ||
| for direction in range(4): | ||
| next_row = node[0] + drow[direction] | ||
| next_col = node[1] + dcol[direction] | ||
| if 0 <= next_row < m and 0 <= next_col < n and grid[next_row][next_col] == '1': | ||
| neighbors.append((next_row, next_col)) | ||
| return neighbors | ||
|
|
||
| total = 0 | ||
| for i in range(m): | ||
| for j in range(n): | ||
| if grid[i][j] == '1' and not visited[i][j]: | ||
| dfs((i, j)) | ||
| total += 1 | ||
|
|
||
| return total |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| class Solution: | ||
| def numIslands(self, grid: List[List[str]]) -> int: | ||
| LAND = '1' | ||
| WATER = '0' | ||
| n_row = len(grid) | ||
| n_col = len(grid[0]) | ||
| visited = [[False] * n_col for _ in range(n_row)] | ||
|
|
||
| def explore_island(node: tuple): | ||
| que = deque() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. これもdfsに近いものを感じます。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 関数名よりはたしかに変数のほうが、構わない(変数名が i でもいい場合がある)んですが、上から読んでいってできるだけパズルを作らないというのが大事です。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. list でいいならそっちのほうがいいですね。パズル度が下がるので。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @TORUS0818 @oda |
||
| que.append(node) | ||
| while que: | ||
| current_node = que.popleft() | ||
| current_row, current_col = current_node | ||
| visited[current_row][current_col] = True | ||
| for next_node in get_neighbors(current_node): | ||
| next_row, next_col = next_node | ||
| if not visited[next_row][next_col]: | ||
| que.append(next_node) | ||
| visited[next_row][next_col] = True | ||
|
|
||
| def get_neighbors(node: tuple): | ||
| drow = (0, 1, 0, -1) | ||
| dcol = (1, 0, -1, 0) | ||
| neighbors = [] | ||
| for direction in range(4): | ||
| next_row = node[0] + drow[direction] | ||
| next_col = node[1] + dcol[direction] | ||
| if 0 <= next_row < n_row and 0 <= next_col < n_col and grid[next_row][next_col] == LAND: | ||
| neighbors.append((next_row, next_col)) | ||
| return neighbors | ||
|
|
||
| total = 0 | ||
| for i in range(n_row): | ||
| for j in range(n_col): | ||
| if grid[i][j] == LAND and not visited[i][j]: | ||
| explore_island((i, j)) | ||
| total += 1 | ||
|
|
||
| return total | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| class Solution: | ||
| def numIslands(self, grid: List[List[str]]) -> int: | ||
| LAND = '1' | ||
| WATER = '0' | ||
| n_row = len(grid) | ||
| n_col = len(grid[0]) | ||
| visited = [[False] * n_col for _ in range(n_row)] | ||
|
|
||
| def explore_island(node: tuple) -> None: | ||
| current_row, current_col = node | ||
| visited[current_row][current_col] = True | ||
| for next_node in get_neighbors(node): | ||
| next_row, next_col = next_node | ||
| if not visited[next_row][next_col]: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 最初(10行目)にこの判定を持ってきても良いかなと思いました。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. とりあえず渡しておいて、次の人に判定を任せるでもOKですね。 |
||
| explore_island(next_node) | ||
|
|
||
| def get_neighbors(node: tuple) -> list: | ||
| drow = (0, 1, 0, -1) | ||
| dcol = (1, 0, -1, 0) | ||
| neighbors = [] | ||
| for direction in range(4): | ||
| next_row = node[0] + drow[direction] | ||
| next_col = node[1] + dcol[direction] | ||
| if 0 <= next_row < n_row and 0 <= next_col < n_col and grid[next_row][next_col] == LAND: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 長くなるようなら、ここら辺の条件チェックを関数として切り出すと良いかなと思いました。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ありがとうございます。 |
||
| neighbors.append((next_row, next_col)) | ||
|
|
||
| return neighbors | ||
|
|
||
| total = 0 | ||
| for i in range(n_row): | ||
| for j in range(n_col): | ||
| if grid[i][j] == LAND and not visited[i][j]: | ||
| explore_island((i, j)) | ||
| total += 1 | ||
| return total | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| class Solution: | ||
| def numIslands(self, grid: List[List[str]]) -> int: | ||
| LAND = '1' | ||
| WATER = '0' | ||
| num_rows = len(grid) | ||
| num_cols = len(grid[0]) | ||
| visited = [[False] * num_cols for _ in range(num_rows)] | ||
|
|
||
| def explore_island(row, col): | ||
| visited[row][col] = True | ||
| directions = [(0, 1), (1, 0), (-1, 0), (0, -1)] | ||
| for delta_row, delta_col in directions: | ||
| next_row = row + delta_row | ||
| next_col = col + delta_col | ||
| if not (0 <= next_row < num_rows and 0 <= next_col < num_cols): continue | ||
| if grid[next_row][next_col] == WATER: continue | ||
| if visited[next_row][next_col]: continue | ||
| explore_island(next_row, next_col) | ||
|
|
||
| total = 0 | ||
| for i in range(num_rows): | ||
| for j in range(num_cols): | ||
| if grid[i][j] == LAND and not visited[i][j]: | ||
| explore_island(i, j) | ||
| total += 1 | ||
| return total |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご参考
https://discord.com/channels/1084280443945353267/1183683738635346001/1197738650998415500