From 006f3f89fa998b8093681c82e12af3bcc670ee59 Mon Sep 17 00:00:00 2001 From: tom4649 Date: Sat, 28 Mar 2026 14:32:03 +0900 Subject: [PATCH 1/2] 63. Unique Paths II --- 63/memo.md | 24 ++++++++++++++++++++++++ 63/sol1.py | 21 +++++++++++++++++++++ 63/sol2.py | 19 +++++++++++++++++++ 63/sol3.py | 30 ++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 63/memo.md create mode 100644 63/sol1.py create mode 100644 63/sol2.py create mode 100644 63/sol3.py diff --git a/63/memo.md b/63/memo.md new file mode 100644 index 0000000..48e5c19 --- /dev/null +++ b/63/memo.md @@ -0,0 +1,24 @@ +# 63. Unique Paths II + +- sol1.py: dpでかいた +- sol2.py: 初期化方法と変数名を改善 + +https://github.com/olsen-blue/Arai60/pull/34#pullrequestreview-2636297197 +> コンパイラ言語ではif文(機械語にしたときの分岐命令)って(分岐予測に失敗するとパイプラインの工程を最初からやり直さないといけないので)他の命令より時間がかかるんです +> なので、可読性の面でも速度の面でもこのfor文は分けた方がよりよいですね +>でも、Pythonはインタプリタ言語(そもそもプログラムの解釈・実行に大量に分岐命令が使われてると思う)なので速度の観点では気にするような速度差は生まれないかもしれません + +これは勉強になった。 +つまり、CやRustなどんコンパイラ言語では、分岐予測に失敗するとオーバーヘッドが発生するので、for文内のif文はなるべく分けた方が良い。 +つまり、事前に決まっている分岐(0行目or0列目など)はfor文の外で行った方が良い。 +しかし、Pythonの場合はこれを気にする必要はなさそう。 + + +https://github.com/Fuminiton/LeetCode/pull/34#discussion_r2052772608 +> [0][0]にアクセスする前に一応チェックしてもいいかもしれませんね。問題文に制約があるにせよ。 + +これはたまたまできていた + +https://algo-method.com/descriptions/78 +配るDPともらうDP +配るDPで書いた:sol3.py diff --git a/63/sol1.py b/63/sol1.py new file mode 100644 index 0000000..69d962b --- /dev/null +++ b/63/sol1.py @@ -0,0 +1,21 @@ +class Solution: + def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: + if not obstacleGrid or not obstacleGrid[0]: + return 0 + + m, n = len(obstacleGrid), len(obstacleGrid[0]) + + 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] + + for row in range(1, m): + for col in range(0, n): + if obstacleGrid[row][col]: + unique_paths_per_row[col] = 0 + continue + if col == 0: + continue + unique_paths_per_row[col] += unique_paths_per_row[col - 1] + + return unique_paths_per_row[-1] diff --git a/63/sol2.py b/63/sol2.py new file mode 100644 index 0000000..152c938 --- /dev/null +++ b/63/sol2.py @@ -0,0 +1,19 @@ +class Solution: + def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: + if not obstacleGrid or not obstacleGrid[0]: + return 0 + + 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 + + for row in range(n_row): + for col in range(n_col): + 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] + + return unique_paths_per_row[-1] diff --git a/63/sol3.py b/63/sol3.py new file mode 100644 index 0000000..02d7c69 --- /dev/null +++ b/63/sol3.py @@ -0,0 +1,30 @@ +class Solution: + def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: + if not obstacleGrid or not obstacleGrid[0]: + return 0 + + 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 + + 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 + + ways = unique_paths_per_row[col] + if ways == 0: + continue + + 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 row + 1 < n_row: + unique_paths_per_row = unique_paths_next_row + + return unique_paths_per_row[-1] From 8b1969c68dc4c4254f32e377f747801ef2a03fb7 Mon Sep 17 00:00:00 2001 From: tom4649 Date: Sun, 29 Mar 2026 05:34:39 +0900 Subject: [PATCH 2/2] Apply suggestion --- 63/sol1.py | 22 +++++++++++++++------- 63/sol3.py | 12 ++++++------ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/63/sol1.py b/63/sol1.py index 69d962b..3c73c10 100644 --- a/63/sol1.py +++ b/63/sol1.py @@ -3,15 +3,23 @@ def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: if not obstacleGrid or not obstacleGrid[0]: return 0 - m, n = len(obstacleGrid), len(obstacleGrid[0]) + num_rows, num_cols = len(obstacleGrid), len(obstacleGrid[0]) - 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 - for row in range(1, m): - for col in range(0, n): - if obstacleGrid[row][col]: + 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 + + for row in range(1, num_rows): + for col in range(0, num_cols): + if obstacleGrid[row][col] != EMPTY: unique_paths_per_row[col] = 0 continue if col == 0: diff --git a/63/sol3.py b/63/sol3.py index 02d7c69..684a3dd 100644 --- a/63/sol3.py +++ b/63/sol3.py @@ -15,14 +15,14 @@ def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int: unique_paths_per_row[col] = 0 continue - ways = unique_paths_per_row[col] - if ways == 0: + paths = unique_paths_per_row[col] + if paths == 0: continue - 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] += 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