49
49
50
50
## 解法
51
51
52
- ### 方法一:动态规划
52
+ ### 方法一:记忆化搜索
53
53
54
- 我们定义 $dp [ i ] [ j ] $ 表示到达网格 $(i,j)$ 的路径数。
54
+ 我们设计一个函数 $dfs(i, j)$ 表示从网格 $(i, j)$ 到网格 $(m - 1, n - 1)$ 的路径数。其中 $m$ 和 $n$ 分别是网格的行数和列数 。
55
55
56
- 首先初始化 $dp$ 第一列和第一行的所有值,然后遍历其它行和列,有两种情况 :
56
+ 函数 $dfs(i, j)$ 的执行过程如下 :
57
57
58
- - 若 $obstacleGrid[ i] [ j ] = 1$,说明路径数为 $0$,那么 $dp[ i] [ j ] = 0$;
59
- - 若 ¥ obstacleGrid[ i] [ j ] = 0$,则 $dp[ i] [ j ] = dp[ i - 1] [ j ] + dp[ i] [ j - 1 ] $。
58
+ - 如果 $i \ge m$ 或者 $j \ge n$,或者 $obstacleGrid[ i] [ j ] = 1$,则路径数为 $0$;
59
+ - 如果 $i = m - 1$ 且 $j = n - 1$,则路径数为 $1$;
60
+ - 否则,路径数为 $dfs(i + 1, j) + dfs(i, j + 1)$。
60
61
61
- 最后返回 $dp[ m - 1] [ n - 1 ] $ 即可。
62
+ 为了避免重复计算,我们可以使用记忆化搜索的方法。
63
+
64
+ 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是网格的行数和列数。
65
+
66
+ <!-- tabs:start -->
67
+
68
+ ``` python
69
+ class Solution :
70
+ def uniquePathsWithObstacles (self , obstacleGrid : List[List[int ]]) -> int :
71
+ @cache
72
+ def dfs (i : int , j : int ) -> int :
73
+ if i >= m or j >= n or obstacleGrid[i][j]:
74
+ return 0
75
+ if i == m - 1 and j == n - 1 :
76
+ return 1
77
+ return dfs(i + 1 , j) + dfs(i, j + 1 )
78
+
79
+ m, n = len (obstacleGrid), len (obstacleGrid[0 ])
80
+ return dfs(0 , 0 )
81
+ ```
82
+
83
+ ``` java
84
+ class Solution {
85
+ private Integer [][] f;
86
+ private int [][] obstacleGrid;
87
+ private int m;
88
+ private int n;
89
+
90
+ public int uniquePathsWithObstacles (int [][] obstacleGrid ) {
91
+ m = obstacleGrid. length;
92
+ n = obstacleGrid[0 ]. length;
93
+ this . obstacleGrid = obstacleGrid;
94
+ f = new Integer [m][n];
95
+ return dfs(0 , 0 );
96
+ }
97
+
98
+ private int dfs (int i , int j ) {
99
+ if (i >= m || j >= n || obstacleGrid[i][j] == 1 ) {
100
+ return 0 ;
101
+ }
102
+ if (i == m - 1 && j == n - 1 ) {
103
+ return 1 ;
104
+ }
105
+ if (f[i][j] == null ) {
106
+ f[i][j] = dfs(i + 1 , j) + dfs(i, j + 1 );
107
+ }
108
+ return f[i][j];
109
+ }
110
+ }
111
+ ```
112
+
113
+ ``` cpp
114
+ class Solution {
115
+ public:
116
+ int uniquePathsWithObstacles(vector<vector<int >>& obstacleGrid) {
117
+ int m = obstacleGrid.size(), n = obstacleGrid[ 0] .size();
118
+ int f[ m] [ n ] ;
119
+ memset(f, -1, sizeof(f));
120
+ function<int(int, int)> dfs = [ &] (int i, int j) {
121
+ if (i >= m || j >= n || obstacleGrid[ i] [ j ] ) {
122
+ return 0;
123
+ }
124
+ if (i == m - 1 && j == n - 1) {
125
+ return 1;
126
+ }
127
+ if (f[ i] [ j ] == -1) {
128
+ f[ i] [ j ] = dfs(i + 1, j) + dfs(i, j + 1);
129
+ }
130
+ return f[ i] [ j ] ;
131
+ };
132
+ return dfs(0, 0);
133
+ }
134
+ };
135
+ ```
136
+
137
+ ```go
138
+ func uniquePathsWithObstacles(obstacleGrid [][]int) int {
139
+ m, n := len(obstacleGrid), len(obstacleGrid[0])
140
+ f := make([][]int, m)
141
+ for i := range f {
142
+ f[i] = make([]int, n)
143
+ for j := range f[i] {
144
+ f[i][j] = -1
145
+ }
146
+ }
147
+ var dfs func(i, j int) int
148
+ dfs = func(i, j int) int {
149
+ if i >= m || j >= n || obstacleGrid[i][j] == 1 {
150
+ return 0
151
+ }
152
+ if i == m-1 && j == n-1 {
153
+ return 1
154
+ }
155
+ if f[i][j] == -1 {
156
+ f[i][j] = dfs(i+1, j) + dfs(i, j+1)
157
+ }
158
+ return f[i][j]
159
+ }
160
+ return dfs(0, 0)
161
+ }
162
+ ```
163
+
164
+ ``` ts
165
+ function uniquePathsWithObstacles(obstacleGrid : number [][]): number {
166
+ const m = obstacleGrid .length ;
167
+ const n = obstacleGrid [0 ].length ;
168
+ const f: number [][] = Array .from ({ length: m }, () => Array (n ).fill (- 1 ));
169
+ const dfs = (i : number , j : number ): number => {
170
+ if (i >= m || j >= n || obstacleGrid [i ][j ] === 1 ) {
171
+ return 0 ;
172
+ }
173
+ if (i === m - 1 && j === n - 1 ) {
174
+ return 1 ;
175
+ }
176
+ if (f [i ][j ] === - 1 ) {
177
+ f [i ][j ] = dfs (i + 1 , j ) + dfs (i , j + 1 );
178
+ }
179
+ return f [i ][j ];
180
+ };
181
+ return dfs (0 , 0 );
182
+ }
183
+ ```
184
+
185
+ <!-- tabs: end -->
186
+
187
+ ### 方法二:动态规划
188
+
189
+ 我们定义 $f[ i] [ j ] $ 表示到达网格 $(i,j)$ 的路径数。
190
+
191
+ 首先初始化 $f$ 第一列和第一行的所有值,然后遍历其它行和列,有两种情况:
192
+
193
+ - 若 $obstacleGrid[ i] [ j ] = 1$,说明路径数为 $0$,那么 $f[ i] [ j ] = 0$;
194
+ - 若 $obstacleGrid[ i] [ j ] = 0$,则 $f[ i] [ j ] = f[ i - 1] [ j ] + f[ i] [ j - 1 ] $。
195
+
196
+ 最后返回 $f[ m - 1] [ n - 1 ] $ 即可。
62
197
63
198
时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是网格的行数和列数。
64
199
68
203
class Solution :
69
204
def uniquePathsWithObstacles (self , obstacleGrid : List[List[int ]]) -> int :
70
205
m, n = len (obstacleGrid), len (obstacleGrid[0 ])
71
- dp = [[0 ] * n for _ in range (m)]
206
+ f = [[0 ] * n for _ in range (m)]
72
207
for i in range (m):
73
208
if obstacleGrid[i][0 ] == 1 :
74
209
break
75
- dp [i][0 ] = 1
210
+ f [i][0 ] = 1
76
211
for j in range (n):
77
212
if obstacleGrid[0 ][j] == 1 :
78
213
break
79
- dp [0 ][j] = 1
214
+ f [0 ][j] = 1
80
215
for i in range (1 , m):
81
216
for j in range (1 , n):
82
217
if obstacleGrid[i][j] == 0 :
83
- dp [i][j] = dp [i - 1 ][j] + dp [i][j - 1 ]
84
- return dp [- 1 ][- 1 ]
218
+ f [i][j] = f [i - 1 ][j] + f [i][j - 1 ]
219
+ return f [- 1 ][- 1 ]
85
220
```
86
221
87
222
``` java
88
223
class Solution {
89
224
public int uniquePathsWithObstacles (int [][] obstacleGrid ) {
90
225
int m = obstacleGrid. length, n = obstacleGrid[0 ]. length;
91
- int [][] dp = new int [m][n];
226
+ int [][] f = new int [m][n];
92
227
for (int i = 0 ; i < m && obstacleGrid[i][0 ] == 0 ; ++ i) {
93
- dp [i][0 ] = 1 ;
228
+ f [i][0 ] = 1 ;
94
229
}
95
230
for (int j = 0 ; j < n && obstacleGrid[0 ][j] == 0 ; ++ j) {
96
- dp [0 ][j] = 1 ;
231
+ f [0 ][j] = 1 ;
97
232
}
98
233
for (int i = 1 ; i < m; ++ i) {
99
234
for (int j = 1 ; j < n; ++ j) {
100
235
if (obstacleGrid[i][j] == 0 ) {
101
- dp [i][j] = dp [i - 1 ][j] + dp [i][j - 1 ];
236
+ f [i][j] = f [i - 1 ][j] + f [i][j - 1 ];
102
237
}
103
238
}
104
239
}
105
- return dp [m - 1 ][n - 1 ];
240
+ return f [m - 1 ][n - 1 ];
106
241
}
107
242
}
108
243
```
@@ -112,75 +247,96 @@ class Solution {
112
247
public:
113
248
int uniquePathsWithObstacles(vector<vector<int >>& obstacleGrid) {
114
249
int m = obstacleGrid.size(), n = obstacleGrid[ 0] .size();
115
- vector<vector<int >> dp (m, vector<int >(n));
250
+ vector<vector<int >> f (m, vector<int >(n));
116
251
for (int i = 0; i < m && obstacleGrid[ i] [ 0 ] == 0; ++i) {
117
- dp [ i] [ 0 ] = 1;
252
+ f [ i] [ 0 ] = 1;
118
253
}
119
254
for (int j = 0; j < n && obstacleGrid[ 0] [ j ] == 0; ++j) {
120
- dp [ 0] [ j ] = 1;
255
+ f [ 0] [ j ] = 1;
121
256
}
122
257
for (int i = 1; i < m; ++i) {
123
258
for (int j = 1; j < n; ++j) {
124
259
if (obstacleGrid[ i] [ j ] == 0) {
125
- dp [ i] [ j ] = dp [ i - 1] [ j ] + dp [ i] [ j - 1 ] ;
260
+ f [ i] [ j ] = f [ i - 1] [ j ] + f [ i] [ j - 1 ] ;
126
261
}
127
262
}
128
263
}
129
- return dp [ m - 1] [ n - 1 ] ;
264
+ return f [ m - 1] [ n - 1 ] ;
130
265
}
131
266
};
132
267
```
133
268
134
269
```go
135
270
func uniquePathsWithObstacles(obstacleGrid [][]int) int {
136
271
m, n := len(obstacleGrid), len(obstacleGrid[0])
137
- dp := make([][]int, m)
272
+ f := make([][]int, m)
138
273
for i := 0; i < m; i++ {
139
- dp [i] = make([]int, n)
274
+ f [i] = make([]int, n)
140
275
}
141
276
for i := 0; i < m && obstacleGrid[i][0] == 0; i++ {
142
- dp [i][0] = 1
277
+ f [i][0] = 1
143
278
}
144
279
for j := 0; j < n && obstacleGrid[0][j] == 0; j++ {
145
- dp [0][j] = 1
280
+ f [0][j] = 1
146
281
}
147
282
for i := 1; i < m; i++ {
148
283
for j := 1; j < n; j++ {
149
284
if obstacleGrid[i][j] == 0 {
150
- dp [i][j] = dp [i-1][j] + dp [i][j-1]
285
+ f [i][j] = f [i-1][j] + f [i][j-1]
151
286
}
152
287
}
153
288
}
154
- return dp [m-1][n-1]
289
+ return f [m-1][n-1]
155
290
}
156
291
```
157
292
158
293
``` ts
159
294
function uniquePathsWithObstacles(obstacleGrid : number [][]): number {
160
295
const m = obstacleGrid .length ;
161
296
const n = obstacleGrid [0 ].length ;
162
- const dp = Array .from ({ length: m }, () => new Array (n ).fill (0 ));
297
+ const f = Array .from ({ length: m }, () => Array (n ).fill (0 ));
163
298
for (let i = 0 ; i < m ; i ++ ) {
164
299
if (obstacleGrid [i ][0 ] === 1 ) {
165
300
break ;
166
301
}
167
- dp [i ][0 ] = 1 ;
302
+ f [i ][0 ] = 1 ;
168
303
}
169
304
for (let i = 0 ; i < n ; i ++ ) {
170
305
if (obstacleGrid [0 ][i ] === 1 ) {
171
306
break ;
172
307
}
173
- dp [0 ][i ] = 1 ;
308
+ f [0 ][i ] = 1 ;
174
309
}
175
310
for (let i = 1 ; i < m ; i ++ ) {
176
311
for (let j = 1 ; j < n ; j ++ ) {
177
312
if (obstacleGrid [i ][j ] === 1 ) {
178
313
continue ;
179
314
}
180
- dp [i ][j ] = dp [i - 1 ][j ] + dp [i ][j - 1 ];
315
+ f [i ][j ] = f [i - 1 ][j ] + f [i ][j - 1 ];
181
316
}
182
317
}
183
- return dp [m - 1 ][n - 1 ];
318
+ return f [m - 1 ][n - 1 ];
319
+ }
320
+ ```
321
+
322
+ ``` ts
323
+ function uniquePathsWithObstacles(obstacleGrid : number [][]): number {
324
+ const m = obstacleGrid .length ;
325
+ const n = obstacleGrid [0 ].length ;
326
+ const f: number [][] = Array .from ({ length: m }, () => Array (n ).fill (- 1 ));
327
+ const dfs = (i : number , j : number ): number => {
328
+ if (i >= m || j >= n || obstacleGrid [i ][j ] === 1 ) {
329
+ return 0 ;
330
+ }
331
+ if (i === m - 1 && j === n - 1 ) {
332
+ return 1 ;
333
+ }
334
+ if (f [i ][j ] === - 1 ) {
335
+ f [i ][j ] = dfs (i + 1 , j ) + dfs (i , j + 1 );
336
+ }
337
+ return f [i ][j ];
338
+ };
339
+ return dfs (0 , 0 );
184
340
}
185
341
```
186
342
@@ -189,31 +345,28 @@ impl Solution {
189
345
pub fn unique_paths_with_obstacles (obstacle_grid : Vec <Vec <i32 >>) -> i32 {
190
346
let m = obstacle_grid . len ();
191
347
let n = obstacle_grid [0 ]. len ();
192
- if obstacle_grid [0 ][0 ] == 1 || obstacle_grid [m - 1 ][n - 1 ] == 1 {
193
- return 0 ;
194
- }
195
- let mut dp = vec! [vec! [0 ; n ]; m ];
348
+ let mut f = vec! [vec! [0 ; n ]; m ];
196
349
for i in 0 .. n {
197
350
if obstacle_grid [0 ][i ] == 1 {
198
351
break ;
199
352
}
200
- dp [0 ][i ] = 1 ;
353
+ f [0 ][i ] = 1 ;
201
354
}
202
355
for i in 0 .. m {
203
356
if obstacle_grid [i ][0 ] == 1 {
204
357
break ;
205
358
}
206
- dp [i ][0 ] = 1 ;
359
+ f [i ][0 ] = 1 ;
207
360
}
208
361
for i in 1 .. m {
209
362
for j in 1 .. n {
210
363
if obstacle_grid [i ][j ] == 1 {
211
364
continue ;
212
365
}
213
- dp [i ][j ] = dp [i - 1 ][j ] + dp [i ][j - 1 ];
366
+ f [i ][j ] = f [i - 1 ][j ] + f [i ][j - 1 ];
214
367
}
215
368
}
216
- dp [m - 1 ][n - 1 ]
369
+ f [m - 1 ][n - 1 ]
217
370
}
218
371
}
219
372
```
0 commit comments