Skip to content
Open
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
89 changes: 89 additions & 0 deletions Python3/62. Unique Paths.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
## Step 1. Initial Solution

- 最初に思い付いたのは数学でよくある方法
- 右に行く方法+下に行く方法の中で右に行く方法を選ぶ
- $_{m+n-2}C_{m-2}$
- ただ、変数の置き方などが難しい

```python
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
# Can be written as _{m+n-2} C _{m-1}
pos_to_move_right = 1
orders_of_move_right = 1
for i in range(m, m + n - 1):
pos_to_move_right *= i
orders_of_move_right *= (i - m + 1)
return pos_to_move_right // orders_of_move_right
```

Copy link

Choose a reason for hiding this comment

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


### Complexity Analysis

- 時間計算量:O(n)
- 空間計算量:O(1)

## Step 2. Alternatives

- DPで求める方法
- 計算量はO(mn)
- 小学校でやりそうな解法

```python
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
paths_to_grid = [[1] * m ] * n
for i in range(1, n):

Choose a reason for hiding this comment

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

リストのコピーではなく、リストに含まれるオブジェクトへの参照をnこ作っていることは認識しておくべきだと思います。

  • If we have a mutable object (list, dict, set, etc.), we can use some specific operations to mutate it and all the variables that refer to it will see the change.
  • If we have an immutable object (str, int, tuple, etc.), all the variables that refer to it will always see the same value, but operations that transform that value into a new value always return a new object.

https://docs.python.org/3/faq/programming.html#why-did-changing-list-y-also-change-list-x

for j in range(1, m):
paths_to_grid[i][j] = \
paths_to_grid[i-1][j] + paths_to_grid[i][j-1]
return paths_to_grid[n-1][m-1]
```

- 他の人の解き方も見る
- https://github.com/fuga-98/arai60/pull/33/files#diff-3d04158956739fa9e3948a043cdcf2a3246498baedcc5098bf90ee92cad790d0R31
- Combinationはライブラリであるらしい
- `return math.comb(m+n-2, m-1)`
- リストを要素の掛け算で作る時の注意点
- https://github.com/fuga-98/arai60/pull/33/files#r2040681343
- 下のようにして作った場合は全て同じオブジェクトを指す
- Before (2,1)がAfter (1,1)を指し、Before (3,1)がAfter(2,1)を指すようになる
- リストの掛け算で長さmの中で同じインデックスの要素が同時に書き換わる
- mutableのコピーなのでpaths_to_grid[i]は全て同じオブジェクト
- どうせ書き換わってしまうなら直前の列だけ保持しておくのと変わりがないので気を付けようと思った

```python
[[1] * m ] * n

Before (1,1)-> ID:10660680, Value: 1
After (1,1)-> ID:10660712, Value: 2
Before (1,2)-> ID:10660680, Value: 1
After (1,2)-> ID:10660744, Value: 3
Before (2,1)-> ID:10660712, Value: 2
After (2,1)-> ID:10660744, Value: 3
Before (2,2)-> ID:10660744, Value: 3
After (2,2)-> ID:10660840, Value: 6
Before (3,1)-> ID:10660744, Value: 3
After (3,1)-> ID:10660776, Value: 4
```

- https://github.com/saagchicken/coding_practice/pull/19/files
- 二次元配列の場合はCとかだと連続メモリに値を入れる都合上、内側のループを右の添字にする感覚がある
- 答えの出し方を[-1][-1]にするのはあり
- https://discord.com/channels/1084280443945353267/1301587996298182696/1340483985972658227
- row, colでループを回す方が自然とのこと

## Step 3. Final Solution

- コンビネーションは簡単すぎるのでDPで実装練習
- 直前の列だけ保持する方針で実装

```python
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
paths_to_col = [1] * m
for _ in range(1, n):
for row in range(1, m):
paths_to_col[row] += paths_to_col[row-1]
return paths_to_col[-1]
```
Copy link

Choose a reason for hiding this comment

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

読みやすいです。