Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions 62/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 62. Unique Paths

- sol1.py
- 高校数学の問題として捉えコーディングの要素は考えていない
- mとnの大小関係を考慮した
- 計算量 O(min(m, n))
- https://github.com/mamo3gr/arai60/blob/62_unique-paths/62_unique-paths/step1_dp.py
- DPで解く。メモ化再帰
- https://docs.python.org/3.13/library/functools.html#functools.lru_cache
- 知らなかった
- https://github.com/mamo3gr/arai60/blob/62_unique-paths/62_unique-paths/step2.py
- メモ化再帰
- 必要のないメモを削除して、メモリを削減していく過程がわかりやすい
- 最後のコードだけ真似する

おまけ
- https://github.com/fuga-98/arai60/pull/33
- リストの宣言法の違いなど
> リストを掛け算で長くすると中身が同じオブジェクトを指すことになるが、数字の場合は immutable で += などをしてもオブジェクトが作り直されるので大きな問題がないが、リストのように mutable なオブジェクトを掛け算で複製すると、実態はひとつなので、一つを変更するとすべてが変更されたように見える、ということです。
- つまり、pythonのlistはオブジェクトのポインタを管理している。immutableなintなどを変更すると、新しいオブジェクトが作られてlistのポインタも別のアドレスに変わるため、そのオブジェクトだけが変わる。一方でmutableなlistなどを変更すると、そのオブジェクトが変更されてlistのポインタは変わらないため、そのポインタを格納しているlistの要素が全て変わったように見える。

```python
>>> a = [1]*10
>>> a
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
>>> a[0] = 2
>>> a
[2, 1, 1, 1, 1, 1, 1, 1, 1, 1]
>>> b = [[1]]*10
>>> b[0][0] = 2
>>> b
[[2], [2], [2], [2], [2], [2], [2], [2], [2], [2]]
>>> b = [[1] for _ in range(10)]
>>> b[0][0] = 2
>>> b
[[2], [1], [1], [1], [1], [1], [1], [1], [1], [1]]
```


13 changes: 13 additions & 0 deletions 62/sol1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
total = 1
if m < n:
m, n = n, m

for i in range(m, m + n - 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.

数学の階乗の形 ((m + n - 2)! / (m - 1)!) に対応させて

for i in range(m + n - 2, m - 1, -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.

たしかにその組み合わせの式が頭にある人に対してはこの書き方が良さそうですが、ここではこのままにしておきます。
そこまで考えてコードを書いているんだと勉強になりました。

total *= i

for i in range(1, n):
total //= i

return total
12 changes: 12 additions & 0 deletions 62/sol2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from functools import lru_cache


class Solution:
def uniquePaths(self, m: int, n: int) -> int:
@lru_cache(maxsize=None)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

メモリの使用量を明示・制限しないなら、functools.cache の方が意図が明確になるかもしれません。Least Recently Used Cache ではなく、全てをcacheしていると思うので。

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.

他の人の真似をして自分で何も考えられていませんでした。こちらの方が良さそうですね。
https://docs.python.org/3/library/functools.html#functools.cache

def count_unique_paths(a, b):
if a == 1 or b == 1:
return 1
return count_unique_paths(a - 1, b) + count_unique_paths(a, b - 1)

return count_unique_paths(m, n)
12 changes: 12 additions & 0 deletions 62/sol3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
if n < m:
m, n = n, m

unique_paths_per_row = [1] * m

for _ in range(1, n):
for col in range(1, m):
unique_paths_per_row[col] += unique_paths_per_row[col - 1]

return unique_paths_per_row[-1]