-
Notifications
You must be signed in to change notification settings - Fork 0
200. Number of Islands.md #16
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,159 @@ | ||
URL: https://leetcode.com/problems/number-of-islands/description/ | ||
|
||
# Step 1 | ||
|
||
- 実装時間: 10分 | ||
- 高さn、幅mのマップとして、 | ||
- 時間計算量: O(nm) | ||
- 空間計算量: O(nm) | ||
|
||
```python | ||
class Solution: | ||
def numIslands(self, grid: List[List[str]]) -> int: | ||
num_island = 0 | ||
visited = set() | ||
for row in range(len(grid)): | ||
for column in range(len(grid[0])): | ||
if (row, column) in visited or grid[row][column] == '0': | ||
continue | ||
num_island += 1 | ||
islands = [(row, column)] | ||
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. island(島)は'1'(陸)の集合なのでlandsの方が正確だと思います 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. ありがとうございます! 自分メモ: |
||
while islands: | ||
island_row, island_column = islands.pop() | ||
if (island_row, island_column) in visited or grid[island_row][island_column] == '0': | ||
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. このチェックを append() の直前に入れると、 append() と pop() の回数が減り、少し処理が軽くなると思います。ただ、好みの問題かもしれません。 |
||
continue | ||
|
||
visited.add((island_row, island_column)) | ||
for dy, dx in [(0, 1), (1, 0), (0, -1), (-1, 0)]: | ||
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. ここの順序が気になりました。1,2,3,4の全ての順序を書き出すときに、1234から始めて1243, 1324, 1342, ... のように接頭辞12を固定して、次は接頭辞を13に固定して、、、という風にすることによって抜け漏れがないように工夫すると思います。 |
||
if 0 <= island_row + dy < len(grid) and 0 <= island_column + dx < len(grid[0]): | ||
islands.append((island_row + dy, island_column + dx)) | ||
|
||
return num_island | ||
``` | ||
|
||
# Step 2 | ||
|
||
- 参考にしたURL | ||
- https://github.com/Hurukawa2121/leetcode/pull/17 | ||
- https://github.com/colorbox/leetcode/pull/31 | ||
- https://github.com/haniwachann/leetcode/pull/3 | ||
- https://github.com/tarinaihitori/leetcode/pull/17 | ||
- https://github.com/hroc135/leetcode/pull/17 | ||
- https://github.com/seal-azarashi/leetcode/pull/17 | ||
- https://github.com/thonda28/leetcode/pull/15 | ||
- https://github.com/goto-untrapped/Arai60/pull/38 | ||
- https://github.com/Ryotaro25/leetcode_first60/pull/18 | ||
- https://github.com/Yoshiki-Iwasa/Arai60/pull/16 | ||
- https://github.com/Mike0121/LeetCode/pull/34 | ||
- https://github.com/tshimosake/arai60/pull/8 | ||
- https://github.com/kazukiii/leetcode/pull/18 | ||
- https://github.com/TORUS0818/leetcode/pull/19 | ||
|
||
- 考えられるアプローチ | ||
- スタックデータ構造 | ||
- https://github.com/Hurukawa2121/leetcode/pull/17/files#r1898905955 | ||
- BFS | ||
- Union Find | ||
- gridの値に-1(visited)や0を書き込んでいく | ||
- 入力である grid に対する破壊的な変更は避けたほうがよい | ||
- https://github.com/hroc135/leetcode/pull/17/files#r1750534861 | ||
|
||
- '0'がマジックナンバーとなっているので、定数化かコメントの付与があると読みやすくなりそうです。 | ||
- https://github.com/Hurukawa2121/leetcode/pull/17/files#r1898871301 | ||
|
||
- `visited`という変数名の代わりに`seen`を使ってる。 | ||
- https://github.com/Hurukawa2121/leetcode/pull/17/files | ||
|
||
- > row, col を使う場合、その最大値として height, width を使うのは違和感があります。 | ||
- この感覚は持てていなかったので学び。 | ||
- https://github.com/colorbox/leetcode/pull/31/files#r1881784335 | ||
|
||
- 範囲チェックを関数化するか悩んだけど、1度しか使わないから不要と思ってやらなかった。 | ||
- より複雑な場合は、「名前をつける」という意味で関数にしてもいいパターンがありそう。 | ||
- https://github.com/colorbox/leetcode/pull/31/files#r1885062583 | ||
|
||
- 命名に悩んでいた`dx, dy` | ||
- > x, y の代わりに delta_row, delta_col としたほうが分かりやすいと感じました。 | ||
- https://github.com/tarinaihitori/leetcode/pull/17#discussion_r1840350347 | ||
|
||
- `len(grid)`も変数に置いておく | ||
- `number_of_rows = len(grid)` | ||
- https://github.com/tarinaihitori/leetcode/pull/17/files#r1840491336 | ||
|
||
- traverseの辞書的な意味を知らなかったので調べた。 | ||
- to cover or extend over an area or time period.(地域や期間をカバーする、または拡張する。) | ||
- https://www.ei-navi.jp/dictionary/content/traverse/?utm_source=chatgpt.com | ||
|
||
- ひとつのセルに対する処理を、関数に分割している人が多かった。 | ||
- 他の方のコードを見た後に、自分のコードを見てみるとネストが深い感じがした。 | ||
- 書いている時には気にならなかったので、他者の目線がたりない。 | ||
|
||
```python | ||
class Solution: | ||
def numIslands(self, grid: List[List[str]]) -> int: | ||
WATER = '0' | ||
LAND = '1' | ||
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. この定数が未使用なので消してしまって良さそうですね。 |
||
num_island = 0 | ||
seen = set() | ||
|
||
def traverse(start_row: int, start_column: int) -> None: | ||
islands = [(start_row, start_column)] | ||
while islands: | ||
row, column = islands.pop() | ||
if (row, column) in seen or grid[row][column] == WATER: | ||
continue | ||
seen.add((row, column)) | ||
for delta_row, delta_column in [(0, 1), (1, 0), (0, -1), (-1, 0)]: | ||
next_row = row + delta_row | ||
next_column = column + delta_column | ||
if 0 <= next_row < len(grid) and 0 <= next_column < len(grid[0]): | ||
islands.append((next_row, next_column)) | ||
|
||
for row in range(len(grid)): | ||
for column in range(len(grid[0])): | ||
if (row, column) in seen or grid[row][column] == WATER: | ||
continue | ||
num_island += 1 | ||
traverse(row, column) | ||
return num_island | ||
``` | ||
|
||
# Step 3 | ||
|
||
- 実装時間: 4分 | ||
- 高さn、幅mのマップとして、 | ||
- 時間計算量: O(nm) | ||
- 空間計算量: O(nm) | ||
|
||
```python | ||
class Solution: | ||
def numIslands(self, grid: List[List[str]]) -> int: | ||
num_island = 0 | ||
seen = set() | ||
WATER = '0' | ||
|
||
def traverse(start_row: int, start_col: int) -> None: | ||
islands = [(start_row, start_col)] | ||
while islands: | ||
row, col = islands.pop() | ||
if (row, col) in seen or grid[row][col] == WATER: | ||
continue | ||
seen.add((row, col)) | ||
for delta_row, delta_col in [(0,1), (1,0), (0,-1), (-1,0)]: | ||
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. 個人的には、この四方向を一般化するよりは書き下したほうが読みやすいと思います。 append(row, col - 1)
append(row, col + 1)
append(row - 1, col)
append(row + 1, 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. 個人的には四方向を一般化する書き方のほうが好きです。現場においては、チームの平均的なメンバーが最短で正確に認知負荷低く読める書き方を選ぶのが良いと思います。 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. 自分もこれくらいの処理なら書き下し派ですかね、8方向見るとか、それぞれに他の共通処理があるなどすれば一般化したくなるかなという感じです |
||
next_row = row + delta_row | ||
next_col = col + delta_col | ||
if 0 <= next_row < len(grid) and 0 <= next_col < len(grid[0]): | ||
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. このチェックは、pop の後に回すこともできますね。 |
||
islands.append((next_row, next_col)) | ||
|
||
for row in range(len(grid)): | ||
for col in range(len(grid[0])): | ||
if (row, col) in seen or grid[row][col] == WATER: | ||
continue | ||
num_island += 1 | ||
traverse(row, 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. traverse もう少し説明的な名前でもいいかもしれません。 |
||
return num_island | ||
``` | ||
|
||
- 書いている時に気づいたこと。 | ||
- `column`は`col`とすることで、`row`と文字数が揃う。 | ||
- 省略は基本避けるがcolは共通認識があって許容範囲だと思った。 |
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.
Go言語のgoogleスタイルガイドには変数名に型名を入れないようにとあり、num_islandよりisland_countのような変数名が好まれます。Pythonのスタイルガイドに似た記述がないか見てみましたが見つからなかったです。動的型付け言語では許容されるのかもしれません
参考: https://google.github.io/styleguide/go/decisions#variable-names
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.
ご指摘ありがとうございます!
ご指摘の変数名に型名を入れないほうがいいという感覚は、Pythonでも共通のようです。
sakupan102/arai60-practice#13 (comment)
僕も同じ感覚でして、今回の
num_
はpythonでいうところのint型などの整数型のつもりではなく、numberという英単語のつもりでした。ですが、ご指摘の通り、個数を表すならcountの方がより表現できているなと気づきました。(また、numなら伝わるかもとは思いましたが、そもそも英単語の省略もイマイチでしたね。。。)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.
変数名として正しくは、
number_of_islands
でただこれだと長くてnum_islands
に略してもまあ伝わるかなという感覚です。まあ命名はチームのルールに合わせるのが良いと思うので、チームのみんながnum_
が分かりにくいということであれば、countもありだと思います