-
Notifications
You must be signed in to change notification settings - Fork 0
63 unique paths ii medium #25
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?
Conversation
… better encapsulation
| # @lc code=start | ||
| class Solution: | ||
| def uniquePathsWithObstacles(self, obstacleGrid: list[list[int]]) -> int: | ||
| if not obstacleGrid: |
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.
これだけだと[[]]みたいなのはエラーになりそうですね。
| num_paths_from_left = num_paths_in_row[column - 1] if column > 0 else 0 | ||
| num_paths_in_row[column] = num_paths_from_top + num_paths_from_left | ||
|
|
||
| return num_paths_in_row[-1] |
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.
読みやすいと思います。
ただ大体のケースではこれぐらいの空間計算量だったら削減せずに二次元配列を作ってしまったほうが良い気もします。
| num_paths_in_row[column] = 0 | ||
| continue | ||
| if column > 0: | ||
| num_paths_in_row[column] += num_paths_in_row[column - 1] |
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.
このバージョンはちょっと理解するのに時間かかりました。個人的にはこの行を
num_paths_in_row[column] = num_paths_in_row[column] + num_paths_in_row[column - 1]
と書くと少しわかりやすくなるかもしれないと思いました。
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.
レビューありがとうございます。確かにそうですね。
自分自身、このバージョンは簡潔だけど読みづらいなーという印象でしたが、そのように書けば少し改善されると思いました。
| OBSTACLE = 1 | ||
| num_rows = len(obstacleGrid) | ||
| num_columns = len(obstacleGrid[0]) | ||
| unique_paths = [0] * num_columns |
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.
unique_paths という変数名からは、ユニークなパスのリストまたは集合というニュアンスを感じました。 step2 の num_paths_in_row や num_paths のほうが良いと思いました。
| OBSTACLE = 1 | ||
| num_rows = len(obstacleGrid) | ||
| num_columns = len(obstacleGrid[0]) | ||
| num_paths_in_row = [0] * num_columns |
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.
num_paths_in_rowだとnumber of pathsと捉えて整数と思ったので、path_counts_in_rowなどとするとパスの数の配列であることが明確になりそうだと思いました!
| if not obstacleGrid: | ||
| return 0 | ||
|
|
||
| OBSTACLE = 1 |
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.
L10 と L14 に OBSTACLE = 1 がありますが消し忘れでしょうか。
| num_paths = [[0] * num_columns for _ in range(num_rows)] | ||
|
|
||
| if obstacleGrid[0][0] == OBSTACLE: | ||
| return 0 |
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.
好みかもしれませんが、early return するかどうかの処理は L11 行近くにまとめておきたいなと思いました。
| num_paths_from_left = num_paths_in_row[column - 1] if column > 0 else 0 | ||
| num_paths_from_top = num_paths_in_row[column] if row > 0 else 0 | ||
| num_paths_in_row[column] = num_paths_from_left + num_paths_from_top |
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.
ちょっと分かっていないんですが、これもう少し整理できませんか。row == 0 の場合、元々0が入っているはずなので、
num_paths_from_top == num_paths_in_row[column] のはずで、そうならば、
num_paths_in_row[column] += num_paths_from_left ですかね。
if column > 0:
num_paths_in_row[column] += num_paths_in_row[column - 1]くらいになりますか?
個人的な感覚、大体の場合、三項演算子は使わないほうが単純になるという感覚があります。
問題へのリンク
63. Unique Paths II
言語
Python
自分の解法
step1
各マスを順に見ていき、上隣と左隣からの経路数を足し合わせることで、そのマスまでの経路数を求める。障害物があるマスでは経路数を0にすればOK。
if obstacleGrid[row][column] == OBSTACLE:...の前にif row == 0 and column == 0:...を置いてしまっていた。mを行数、nを列数とすると、O(m * n)O(n)mかnのどちらかが非常に大きい/小さいことがあらかじめわかっている場合、O(min(m, n))に最適化可能O(m * n)で解き、次に一次元配列を使ってO(n)に最適化する、というステップを踏んだ。step2
num_paths_from_leftとnum_paths_from_topの計算を三項演算子で簡潔に書いた。num_paths_in_row[column] if row > 0 else 0は実は不要で、num_paths_in_row[column]だけで良いが、可読性を優先した。if row == 0 and column == 0:をif row == column == 0:と書いた。例えば、以下のようにすれば
とすれば、
if row == 0 and column == 0:の条件分岐は不要になってスッキリはするが、num_paths_from_leftとnum_paths_from_topとして明示的に書く方が、アルゴリズムの意図がわかりやすいと考えた。step3
step4 (FB)
別解・模範解答
配るDP:
distribute_dp.pyO(m * n)O(m * n)本問の場合、1次元DPで配るDPは、アルゴリズムとして不自然な気がする。
想定されるフォローアップ質問
次に解く問題の予告