-
Notifications
You must be signed in to change notification settings - Fork 0
62. Unique Paths #35
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?
62. Unique Paths #35
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,141 @@ | ||
| # Step1 | ||
|
|
||
| かかった時間:9min | ||
|
|
||
| 計算量:gridのマスの数をN(m * n)として | ||
|
|
||
| 時間計算量:O(N) | ||
|
|
||
| 空間計算量:O(N) | ||
|
|
||
| DP | ||
| ```python | ||
| class Solution: | ||
| def uniquePaths(self, m: int, n: int) -> int: | ||
| # 壁際のマスへの行き方は1通りしかないのでgridの初期化の際に1で埋める | ||
| grid = [] | ||
| for row_i in range(m): | ||
|
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. suffix の _i は何を表していますか?もし index を表しているのであれば、単に row/col でも十分に意味は伝わると思いますので、消してよいと思います。
Owner
Author
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. indexです。 |
||
| if row_i == 0: | ||
| grid.append([1] * n) | ||
| continue | ||
| grid.append([1] + [0] * (n - 1)) | ||
|
|
||
| for row_i in range(1, m): | ||
| for col_i in range(1, n): | ||
| grid[row_i][col_i] = grid[row_i - 1][col_i] + grid[row_i][col_i - 1] | ||
|
|
||
| return grid[m - 1][n - 1] | ||
| ``` | ||
| 思考ログ: | ||
| - 小学生の時にやったマスの上と左に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. 自分も思いました |
||
| - 問題文につられて```grid```にしたが、```num_ways```とかにした方が情報があって良かったか | ||
| - ある座標[i, j]への行き方の総数を記録した二次元配列 | ||
| - ```grid```の作成と壁際の初期化を同時にやってしまったが、冗長でも分けても良かったかもしれない | ||
|
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. 念の為、 grid = [[0] * n] * mが違うものは出来上がるということをコメントしておきます。
Owner
Author
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. ありがとうございます。 浅いコピーの話ですね。 |
||
|
|
||
| 組み合わせを計算 | ||
| ```python | ||
| from scipy.special import comb | ||
|
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. mathじゃなくてscipyのcombを使っているのはなにか理由があるんですか?
Owner
Author
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. あまり深い意味はないのですが、皆さんmathを使っていたのでバラエティをと思いまして。 mathのcombはpython3.8から追加されたようですね。 |
||
|
|
||
|
|
||
| class Solution: | ||
| def uniquePaths(self, m: int, n: int) -> int: | ||
| return comb(m - 1 + n - 1, n - 1, exact=True) | ||
| ``` | ||
| 思考ログ: | ||
| - 組み合わせを計算する | ||
| - 例えば、m = 3, n = 3の場合 | ||
| - (↓, ↓, →, →)の並べ方を考えればいい(=4C2) | ||
| - scipy.comb | ||
| - https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.comb.html | ||
| - https://github.com/scipy/scipy/blob/v1.14.1/scipy/special/_basic.py#L2681-L2753 | ||
| - n-1とm-1の小さい方を入れた方が効率がいいかなと思ったが、実装を見たら(_comb_intの中で)やってるようなので気にしないことに | ||
| - https://github.com/scipy/scipy/blob/70455fcdc8c0737ac24b592c74083837ca6fbf72/scipy/special/_comb.pyx#L5 | ||
|
|
||
| # Step2 | ||
|
|
||
| 講師役目線でのセルフツッコミポイント: | ||
|
|
||
| 参考にした過去ログなど: | ||
| - https://github.com/Ryotaro25/leetcode_first60/pull/39 | ||
| - https://github.com/seal-azarashi/leetcode/pull/31 | ||
| - https://github.com/Yoshiki-Iwasa/Arai60/pull/47 | ||
| - https://github.com/nittoco/leetcode/pull/26 | ||
| - 再帰 | ||
| - mathモジュールの話題 | ||
| - https://github.com/nittoco/leetcode/pull/26/files#r1677082520 | ||
|
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. あ、コードを読むのは書くのよりも大事なのでどこかからはやるようにして欲しいです。
Owner
Author
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. はい。一応全ての過去ログ(PR)にはリンク先も含め目を通しているのですが、なかなか時間がかかってしまってます。。 読み書きの比率が読みに偏っていること自体は問題ないのだと思うのですが、正直なところを白状すると、いまだに人のコードを読んだりドキュメントを読んだりということが自然に出来ている感覚がなく、(推奨されているから)頑張ってやっている、感が少なからずあります。 これは単純にやり方が悪いのか、マインドセットの問題なのか、解消の糸口が見つからずにいます。 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. うーん、PR はともかくプロダクションのコードは誰かが誰かに使ってもらうために作っているものである、という面はありますね。 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. そうですね〜、自分も仕事でコード書くときに、急いでたりするとなかなかドキュメントが見れないでいます(データ分析だと、プロダクションコードじゃないので意識が希薄になってしまいがちというのもあるのかも) |
||
| - https://github.com/fhiyo/leetcode/pull/34 | ||
| - 任意精度演算の話 | ||
| - https://zenn.dev/yukinarit/articles/afb263bf68fff2 | ||
| - https://github.com/goto-untrapped/Arai60/pull/32 | ||
| - https://github.com/YukiMichishita/LeetCode/pull/14 | ||
| - https://github.com/sakupan102/arai60-practice/pull/34 | ||
| - combinationsの再帰(というか分解) | ||
| - https://github.com/SuperHotDogCat/coding-interview/pull/16 | ||
| - https://github.com/shining-ai/leetcode/pull/32 | ||
| - https://github.com/hayashi-ay/leetcode/pull/39 | ||
| - 末尾再帰 | ||
|
|
||
| DPの配列を圧縮(空間計算量:O(min(n, m))) | ||
| ```python | ||
| class Solution: | ||
| def uniquePaths(self, m: int, n: int) -> int: | ||
| if n < m: | ||
| n, m = m, n | ||
|
|
||
| num_ways = [1] * n | ||
| for row_i in range(1, m): | ||
| for col_i in range(1, n): | ||
| num_ways[col_i] = num_ways[col_i] + num_ways[col_i - 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. step3 のように、
Owner
Author
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. ありがとうございます。 |
||
|
|
||
| return num_ways[-1] | ||
| ``` | ||
| 思考ログ: | ||
| - 確かに上書きしていけば二次元配列は必要ない | ||
| - n, mの小さい方で配列を確保すればよりエコ | ||
| - そこまで気にする必要はないかもしれないが、追加の処理も少ないのでやっておいてもいいのではという気持ち | ||
|
|
||
| 再帰 | ||
| ```python | ||
| from functools import cache | ||
|
|
||
|
|
||
| class Solution: | ||
| @ cache | ||
| def uniquePaths(self, m: int, n: int) -> int: | ||
| if m == 1 or n == 1: | ||
| return 1 | ||
|
|
||
| return self.uniquePaths(m - 1, n) + self.uniquePaths(m, n - 1) | ||
| ``` | ||
| - cacheを取っておかないと厳しい | ||
| - ただcacheを取れば万事解決というわけでもないのでちゃんと考えて選択する | ||
| - https://github.com/fhiyo/leetcode/pull/34/files | ||
|
|
||
| # Step3 | ||
|
|
||
| かかった時間:2min | ||
|
|
||
| ```python | ||
| class Solution: | ||
| def uniquePaths(self, m: int, n: int) -> int: | ||
| # メモリ節約のため、uniqe path数を管理する配列の長さをmin(n, m)で確保する | ||
| if m < n: | ||
| n, m = m, n | ||
|
|
||
| num_ways = [1] * n | ||
| for _ in range(1, m): | ||
| for i in range(1, n): | ||
| num_ways[i] += num_ways[i - 1] | ||
|
|
||
| return num_ways[-1] | ||
|
Comment on lines
+125
to
+130
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で埋めるのはちょっと抵抗感あるかもという感じで、 num_ways = [0] * n
num_ways[0] = 1
for _ in range(m):
for i in range(1, n):
num_ways[i] += num_ways[i - 1]の方がいいかなと思ったんですが、難しいですね |
||
| ``` | ||
| 思考ログ: | ||
| - 変数名などを修正 | ||
| - いきなりn, mのスワップが始まるとアレかと思いコメントを入れてみたが、もう少しいい説明があったか | ||
|
|
||
| # Step4 | ||
|
|
||
| ```python | ||
| ``` | ||
| 思考ログ: | ||
|
|
||
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_i と col_i が 0 でない場合は加算するという書き方もありますが、どちらがシンプルかは微妙なところです。