Conversation
63/sol1.py
Outdated
| if not obstacleGrid or not obstacleGrid[0]: | ||
| return 0 | ||
|
|
||
| m, n = len(obstacleGrid), len(obstacleGrid[0]) |
There was a problem hiding this comment.
m, n は row, col との対応が分かりにくいので、num_rows, num_cols などと置くといいのではないでしょうか。
63/sol1.py
Outdated
| unique_paths_per_row = [1 - o for o in obstacleGrid[0]] | ||
| for col in range(1, n): | ||
| unique_paths_per_row[col] *= unique_paths_per_row[col - 1] |
There was a problem hiding this comment.
obstacleGrid の要素が 0 あるいは 1 であることを利用した算術による初期化で、ちょっとトリッキーに感じました。例えば障害物の有無を文字列で表すようになったときなど、仕様変更にも弱いように見えます。私がいまパッと書け、と言われたら次のようにします。
| unique_paths_per_row = [1 - o for o in obstacleGrid[0]] | |
| for col in range(1, n): | |
| unique_paths_per_row[col] *= unique_paths_per_row[col - 1] | |
| EMPTY = 0 | |
| if obstacleGrid[0][0] != EMPTY: | |
| return 0 | |
| unique_paths_per_row = [1] + [0] * (n - 1) | |
| for col in range(1, n): | |
| if obstacleGrid[0][col] != EMPTY: | |
| break | |
| unique_paths_per_row[col] = unique_paths_per_row[col - 1] |
偉そうなことを言いながらあんまり上手く書けている気もしないのですが、「左隣 col-1 を引き継ぐ。ただし障害物があったらそこから先はゼロ」感が出るとよいのではないでしょうか。
かなり書き方の幅が広いように思うので、もうちょっと他の人の書き方を漁ってみても良さそうです。
There was a problem hiding this comment.
アドバイスを参考にして以下のように書き直しました。(ほぼ同じですが)
EMPTY = 0
if obstacleGrid[0][0] != EMPTY:
return 0
unique_paths_per_row = [1] + [0] * (num_cols - 1)
col = 1
while col < num_cols and obstacleGrid[0][col] == EMPTY:
unique_paths_per_row[col] = 1
col += 1
63/sol3.py
Outdated
| unique_paths_per_row[col] = 0 | ||
| continue | ||
|
|
||
| ways = unique_paths_per_row[col] |
There was a problem hiding this comment.
path と way は同じ意味で使っているので、英単語も揃えたほうが分かりやすそうです。
63/sol3.py
Outdated
| if col + 1 < n_col and not obstacleGrid[row][col + 1]: | ||
| unique_paths_per_row[col + 1] += ways | ||
| if row + 1 < n_row and not obstacleGrid[row + 1][col]: | ||
| unique_paths_next_row[col] += ways |
There was a problem hiding this comment.
配る相手セルが障害物で潰れているかどうかは、ここでは気にしなくて良さそうです。
| if col + 1 < n_col and not obstacleGrid[row][col + 1]: | |
| unique_paths_per_row[col + 1] += ways | |
| if row + 1 < n_row and not obstacleGrid[row + 1][col]: | |
| unique_paths_next_row[col] += ways | |
| if col + 1 < n_col: | |
| unique_paths_per_row[col + 1] += ways | |
| if row + 1 < n_row: | |
| unique_paths_next_row[col] += ways |
There was a problem hiding this comment.
なるほど、配る側のセルになったときに0になるので処理が重複していましたね
There was a problem hiding this comment.
メモリ使用量が増えるのをやむなしで、2次元配列(フルのテーブル)で書いたほうが、配るDPは分かりやすいと思いました。また、最終行は配らなくていいとか、障害物があったら0に潰して配れない(こっちは最終行も処理する必要がある)、など制御が比較的面倒で、配るよりも貰う方が書きやすそうに感じました。
There was a problem hiding this comment.
「配るよりも貰う方が書きやすそう」は同意します。
配るDPでも直前の二行を保持しておけば良いので、一次元にする必要はないのではないかとと個人的には思います。
There was a problem hiding this comment.
配るDPでも直前の二行を保持しておけば良いので、一次元にする必要はない
そのとおりで、処理的には問題ないのですが、書きやすさ(バグの埋め込みやすさ)・読みやすさの観点からは、2次元配列の方が優れていそうだな、と感じました。unique_paths_per_row と unique_paths_next_row の入れ替え(更新)の必要がなかったり、最終行は入れ替えしないという条件が理解しやすかったりしそうです。
https://leetcode.com/problems/unique-paths-ii/