Add 200. Number of Islands.md#3
Conversation
問題 https://leetcode.com/problems/number-of-islands/description/ 200. Number of Islands Given an m x n 2D binary grid grid which represents a map of '1's (land) and '0's (water), return the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. Example 1: Input: grid = [ ["1","1","1","1","0"], ["1","1","0","1","0"], ["1","1","0","0","0"], ["0","0","0","0","0"] ] Output: 1 Example 2: Input: grid = [ ["1","1","0","0","0"], ["1","1","0","0","0"], ["0","0","1","0","0"], ["0","0","0","1","1"] ] Output: 3 Constraints: m == grid.length n == grid[i].length 1 <= m, n <= 300 grid[i][j] is '0' or '1'.
|
|
||
| 与えられたgridを破壊したくはないけど、どうせvisitedかどうかだけじゃなくて陸地か海か確かめないといけないしからdeep copyして書き込む形にした。deep copyのコストが大きければvisited をsetで作るのもいいかもしれない。 | ||
|
|
||
| 添え字i, jはこの文脈だとわかりにくい?でも毎回row, column と書くのも長いしタイプミスが出そうな気がする。 |
| island = 0 | ||
| for i in range(nr): | ||
| for j in range(nc): | ||
| if grid[i][j] == '1': |
There was a problem hiding this comment.
grid[i][j] == "0"の場合は早期returnしてネスト浅くした方がみやすそうです
| for r in range(num_r): | ||
| for c in range(num_c): | ||
| if not visited[r][c] and grid[r][c] == "1": | ||
| queue.append((r,c)) |
There was a problem hiding this comment.
ネストが深めだと感じました。BFSの部分を関数に切り出すのはどうでしょうか。
| def numIslands(self, grid: List[List[str]]) -> int: | ||
| visited = set() | ||
| num_islands = 0 | ||
| num_r = len(grid) |
There was a problem hiding this comment.
num_r/num\c_ という変数名はあまり見かけないように思います。 num_rows/num_columns のほうが良く見かけるように思います。 num_columns は長いと感じるのであれば num_cols でも十分伝わると思います。
| num_islands = 0 | ||
| num_r = len(grid) | ||
| num_c = len(grid[0]) | ||
| dirs = [(0,1),(1,0),(0,-1),(-1,0)] |
There was a problem hiding this comment.
, のあとにスペースを空けるのと空けないのとが混ざっている点が気になりました。空けるほうに統一することをお勧めいたします。
参考までにスタイルガイドへのリンクを共有いたします。
https://google.github.io/styleguide/pyguide.html#s3.6-whitespace
No whitespace before a comma, semicolon, or colon. Do use whitespace after a comma, semicolon, or colon, except at the end of the line.
なお、このスタイルガイドは“唯一の正解”というわけではなく、数あるガイドラインの一つに過ぎません。チームによって重視される書き方や慣習も異なります。そのため、ご自身の中に基準を持ちつつも、最終的にはチームの一般的な書き方に合わせることをお勧めします。
| num_r = len(grid) | ||
| num_c = len(grid[0]) | ||
| dirs = [(0,1),(1,0),(0,-1),(-1,0)] | ||
| queue = deque() |
There was a problem hiding this comment.
変数名にデータ構造の名前を付けても、読み手にとってあまり情報がないように感じました。中にどのような値が含まれているかを、端的な英単語・英語句で付けるとよいと思います。 cells_to_visit はいかがでしょうか?
| visited.add((r,c)) | ||
| num_islands += 1 | ||
| while queue: | ||
| curr_r, curr_c = queue.popleft() |
There was a problem hiding this comment.
こちらのコメントをご参照ください。
hemispherium/LeetCode_Arai60#10 (comment)
|
いただいたコメントを反映するとこんな感じでしょうか。関数を分割するのをpythonっぽく書くとgridなどを引数で渡すよりinner functionを使う方が一般的なのかなと思ってそうしてみましたが、pythonを仕事では書いたことがないので正直ベストプラクティスはよくわかってないところです。 from collections import deque
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
if not grid or not grid[0]:
return 0
num_row = len(grid)
num_col = len(grid[0])
visited = [[False] * num_col for _ in range(num_row)]
cells_to_visit = deque()
dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)]
num_islands =0
def exploreIsland(r, c):
cells_to_visit.append((r, c))
visited[r][c] = True
while cells_to_visit:
current_row, current_col = cells_to_visit.popleft()
for row_dir, col_dir in dirs:
new_row = current_row + row_dir
new_col = current_col + col_dir
if new_row < 0 or new_row >= num_row or new_col < 0 or new_col >= num_col:
continue
if visited[new_row][new_col] or grid[new_row][new_col] == "0":
continue
visited[new_row][new_col] = True
cells_to_visit.append((new_row, new_col))
for r in range(num_row):
for c in range(num_col):
if visited[r][c] or grid[r][c] == "0":
continue
num_islands += 1
exploreIsland(r, c)
return num_islands |
number of row より number of rows のほうが英語として自然だと思いますので、 num_rows/num_cols とするとよいと思いました。
数直線上に一直線上に並ぶようにしたほうが読みやすくなると思いました。 if not (0 <= new_row < num_row and 0 <= new_col < num_col): |
|
確かにそうですね。さらに書き直すとこんな感じですかね。関数の中で同名の変数を定義したらshadowingが発生するのでこれでも動くんですがややこしいから変数を違う名前にするか迷うところ。 from collections import deque
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
if not grid or not grid[0]:
return 0
num_rows = len(grid)
num_cols = len(grid[0])
num_islands = 0
visited = [[False] * num_cols for _ in range(num_rows)]
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
nodes_to_explore = deque()
def explore_island():
while nodes_to_explore:
row, col = nodes_to_explore.popleft()
for row_dir, col_dir in directions:
new_row = row + row_dir
new_col = col + col_dir
if not (0 <= new_row < num_rows and 0 <= new_col < num_cols):
continue
if visited[new_row][new_col] or grid[new_row][new_col] == "0":
continue
visited[new_row][new_col] = True
nodes_to_explore.append((new_row, new_col))
for row in range(num_rows):
for col in range(num_cols):
if visited[row][col] or grid[row][col] == "0":
continue
visited[row][col] = True
nodes_to_explore.append((row, col))
num_islands += 1
explore_island()
return num_islands |
問題 https://leetcode.com/problems/number-of-islands/description/
Given an m x n 2D binary grid grid which represents a map of '1's (land) and '0's (water), return the number of islands.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
Input: grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
Output: 1
Example 2:
Input: grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
Output: 3
Constraints:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] is '0' or '1'.