Skip to content

63. Unique Paths II#32

Open
tom4649 wants to merge 3 commits intomainfrom
63.Unique-Paths-II
Open

63. Unique Paths II#32
tom4649 wants to merge 3 commits intomainfrom
63.Unique-Paths-II

Conversation

@tom4649
Copy link
Copy Markdown
Owner

@tom4649 tom4649 commented Mar 28, 2026

Comment thread 63/sol1.py Outdated
if not obstacleGrid or not obstacleGrid[0]:
return 0

m, n = len(obstacleGrid), len(obstacleGrid[0])
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m, nrow, col との対応が分かりにくいので、num_rows, num_cols などと置くといいのではないでしょうか。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

採用させていただきました

Comment thread 63/sol1.py Outdated
Comment on lines +8 to +10
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]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obstacleGrid の要素が 0 あるいは 1 であることを利用した算術による初期化で、ちょっとトリッキーに感じました。例えば障害物の有無を文字列で表すようになったときなど、仕様変更にも弱いように見えます。私がいまパッと書け、と言われたら次のようにします。

Suggested change
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 を引き継ぐ。ただし障害物があったらそこから先はゼロ」感が出るとよいのではないでしょうか。

かなり書き方の幅が広いように思うので、もうちょっと他の人の書き方を漁ってみても良さそうです。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

アドバイスを参考にして以下のように書き直しました。(ほぼ同じですが)

        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

Comment thread 63/sol3.py Outdated
unique_paths_per_row[col] = 0
continue

ways = unique_paths_per_row[col]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pathway は同じ意味で使っているので、英単語も揃えたほうが分かりやすそうです。

Comment thread 63/sol3.py Outdated
Comment on lines +22 to +25
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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

配る相手セルが障害物で潰れているかどうかは、ここでは気にしなくて良さそうです。

Suggested change
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

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほど、配る側のセルになったときに0になるので処理が重複していましたね

Comment thread 63/sol3.py
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

メモリ使用量が増えるのをやむなしで、2次元配列(フルのテーブル)で書いたほうが、配るDPは分かりやすいと思いました。また、最終行は配らなくていいとか、障害物があったら0に潰して配れない(こっちは最終行も処理する必要がある)、など制御が比較的面倒で、配るよりも貰う方が書きやすそうに感じました。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

「配るよりも貰う方が書きやすそう」は同意します。
配るDPでも直前の二行を保持しておけば良いので、一次元にする必要はないのではないかとと個人的には思います。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

配るDPでも直前の二行を保持しておけば良いので、一次元にする必要はない

そのとおりで、処理的には問題ないのですが、書きやすさ(バグの埋め込みやすさ)・読みやすさの観点からは、2次元配列の方が優れていそうだな、と感じました。unique_paths_per_rowunique_paths_next_row の入れ替え(更新)の必要がなかったり、最終行は入れ替えしないという条件が理解しやすかったりしそうです。

Comment thread 63/sol1.py
Comment on lines +15 to +18
col = 1
while col < num_cols and obstacleGrid[0][col] == EMPTY:
unique_paths_per_row[col] = 1
col += 1
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

好みの問題ですがcolがこのwhile内でしか使われていないのでfor文にしても良いと思いました.

        for col in range(1, num_cols):
            if obstacleGrid[0][col] != EMPTY:
                break
            unique_paths_per_row[col] = 1

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほど、その書き方もありますね。
ただ今回は「while の条件式の中にループが続く条件を書きたい」という意図で現状のものを採用しようと思います。

Comment thread 63/sol1.py
Comment on lines +15 to +18
col = 1
while col < num_cols and obstacleGrid[0][col] == EMPTY:
unique_paths_per_row[col] = 1
col += 1
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

というかこの箇所なくして後ろのrowに関するforループの範囲を以下のようにすれば動くのではないでしょうか.

for row in range(0, num_rows):

あるマスの値が,その左のマスの値と上のマスの値の和で決まるという仕組みからすると,コメント先の部分の処理を後ろのforループに含んでしまうのも不自然ではないと感じます.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ああ、その通りですね。
sol2.pyでその点を改善した初期化にしたようです。

Comment thread 63/sol2.py
n_row, n_col = len(obstacleGrid), len(obstacleGrid[0])

unique_paths_per_row = [0] * n_col
unique_paths_per_row[0] = 0 if obstacleGrid[0][0] else 1
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obstacleGrid[0][0] == 0の時はsol1.pyのようにearly returnする方が無駄なforループを回さないで済むので好きです.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうですね。分かりやすさの意味でもその方が良いと思うので採用させていただきます。
(書いた時にはまとめて処理できるが良いと考えたんだと思います)

Comment thread 63/sol2.py
Comment on lines +13 to +17
if obstacleGrid[row][col]:
unique_paths_per_row[col] = 0
continue
elif col > 0:
unique_paths_per_row[col] += unique_paths_per_row[col - 1]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

正誤には関係ありませんが,if ... elif ... の形でその後にコードが登場しない場合,if分岐内でのconitnueは不要ですね.
(今後コードを書き加える場合,continueすべきケースとすべきでないケースの両方があり得そうなので特段continueを入れる必要性は感じられませんでした.)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そのとおりですね。If...continueとするならelifではなくifの方が適切ですね。
今回はcontinueを消そうと思います。

Comment thread 63/sol3.py
Comment on lines +11 to +28
for row in range(n_row):
unique_paths_next_row = [0] * n_col
for col in range(n_col):
if obstacleGrid[row][col]:
unique_paths_per_row[col] = 0
continue

paths = unique_paths_per_row[col]
if paths == 0:
continue

if col + 1 < n_col:
unique_paths_per_row[col + 1] += paths
if row + 1 < n_row:
unique_paths_next_row[col] += paths

if row + 1 < n_row:
unique_paths_per_row = unique_paths_next_row
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これは単に好みの問題ですが,sol2.pyで行ったような更新の方が分岐が少なくわかりやすく感じました.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同意します。自分が素直に思いついたのもsol2.pyの方でした。
sol3.pyは配るDPの練習として書きました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants