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 problem34/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
## 取り組み方
- step1: 5分以内に空で書いてAcceptedされるまで解く + テストケースと関連する知識を連想してみる
- step2: 他の方の記録を読んで連想すべき知識や実装を把握した上で、前提を置いた状態で最適な手法を選択し実装する
- step3: 10分以内に1回もエラーを出さずに3回連続で解く

## step1
2次元配列のsum_pathsを基本的に、`sum_paths[r][c] = sum_paths[r-1][c] + sum_paths[r][c-1]`として考える。
今の座標に障害物がない時は上と左の和を組み合わせの数として、障害物があるときは0とすれば良いだけ。

```python
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
OBSTACLE = 1
if obstacleGrid[0][0] == OBSTACLE:
return 0

width = len(obstacleGrid[0])
height = len(obstacleGrid)
sum_paths = [[0] * width for _ in range(height)]
Copy link

Choose a reason for hiding this comment

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

sum_paths を二次元ではなく一次元のリストにしても解くことができると思います。挑戦してみてもよいと思います。

Copy link
Owner Author

Choose a reason for hiding this comment

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

レビューありがとうございます。

ある地点の結果が上と左の結果の和であることを利用して、
ある列の結果を、次の列で再利用する形ですね。

class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        OBSTACLE = 1
        if obstacleGrid is None:
            return -1
        if obstacleGrid[0][0] == OBSTACLE:
            return 0
        height = len(obstacleGrid)
        width = len(obstacleGrid[0])
        num_paths = [0] * width
        num_paths[0] = 1

        for y in range(height):
            for x in range(width):
                if obstacleGrid[y][x] == OBSTACLE:
                    num_paths[x] = 0
                    continue
                if x > 0:
                    num_paths[x] += num_paths[x - 1]
        return num_paths[width - 1]

sum_paths[0][0] = 1
for h in range(1, height):
Copy link

Choose a reason for hiding this comment

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

自分は (width, height) に対しては (x, y) という変数を使うことが多いです。チームの平均的な書き方に合わせることをお勧めいたします。

if obstacleGrid[h][0] == OBSTACLE:
continue
sum_paths[h][0] = sum_paths[h - 1][0]
for w in range(1, width):
if obstacleGrid[0][w] == OBSTACLE:
continue
sum_paths[0][w] = sum_paths[0][w - 1]

for h in range(1, height):
for w in range(1, width):
if obstacleGrid[h][w] == OBSTACLE:
continue
sum_paths[h][w] = sum_paths[h - 1][w] + sum_paths[h][w - 1]
return sum_paths[-1][-1]
```

## step2
### 読んだコード
- https://github.com/hayashi-ay/leetcode/pull/44/files
- https://github.com/SuperHotDogCat/coding-interview/pull/17/files
- https://github.com/sakupan102/arai60-practice/pull/35/files

### 感想
- h>0, w>0 に加算を分けるとかなりスッキリ変形できて良い
Copy link

Choose a reason for hiding this comment

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

これ読みやすいですね

- 地味なところだが、 意図がない限りは height -> width の順で操作することが統一されてる方が適切だと思った
Copy link

Choose a reason for hiding this comment

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

これしていないと書いている本人が一番混乱すると思いますね。


```python
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
OBSTACLE = 1
if obstacleGrid[0][0] == OBSTACLE:
Copy link

Choose a reason for hiding this comment

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

[0][0]にアクセスする前に一応チェックしてもいいかもしれませんね。問題文に制約があるにせよ。

Copy link
Owner Author

Choose a reason for hiding this comment

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

レビューありがとうございます。
空のGridの考慮は完全に抜けてました。

obstacleGrid is None の場合は弾いておくべきですね。

return 0

height, width = len(obstacleGrid), len(obstacleGrid[0])
sum_paths = [[0] * width for _ in range(height)]
sum_paths[0][0] = 1
for h in range(height):
for w in range(width):
if obstacleGrid[h][w] == OBSTACLE:
continue
if h > 0:
sum_paths[h][w] += sum_paths[h - 1][w]
if w > 0:
sum_paths[h][w] += sum_paths[h][w - 1]
return sum_paths[-1][-1]
```

## step3
```python
class Solution:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
OBSTACLE = 1
if obstacleGrid[0][0] == OBSTACLE:
return 0
num_rows = len(obstacleGrid)
num_cols = len(obstacleGrid[0])
sum_paths = [[0] * num_cols for _ in range(num_rows)]

Choose a reason for hiding this comment

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

num_pathsのほうが流れ的に自然でしょうか?

sum_paths[0][0] = 1
for row in range(num_rows):
for col in range(num_cols):
if obstacleGrid[row][col] == OBSTACLE:
Copy link

Choose a reason for hiding this comment

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

十分わかりやすいですが、ループ内が長いのでメソッド化したらより見やすくなりそつです。

Copy link
Owner Author

Choose a reason for hiding this comment

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

レビューありがとうございます。
おっしゃる通りですね。

自分はネストを減らす意識を持つべきかもしれないです。

continue
if row > 0:
sum_paths[row][col] += sum_paths[row - 1][col]
if col > 0:
sum_paths[row][col] += sum_paths[row][col - 1]
return sum_paths[num_rows - 1][num_cols - 1]
```