Skip to content

Commit 05543d9

Browse files
authored
feat: add solutions to lc problem: No.0063 (#4046)
No.0063.Unique Paths II
1 parent f92488f commit 05543d9

File tree

8 files changed

+295
-57
lines changed

8 files changed

+295
-57
lines changed

README_EN.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ This project contains solutions for problems from LeetCode, "Coding Interviews (
1818

1919
[中文文档](/README.md)
2020

21-
## Sites
21+
## Site
2222

23-
https://doocs.github.io/leetcode
23+
https://doocs.github.io/leetcode/en
2424

2525
## Solutions
2626

@@ -31,8 +31,8 @@ https://doocs.github.io/leetcode
3131

3232
## JavaScript & Database Practice
3333

34-
- [JavaScript Practice](/solution/JAVASCRIPT_README_EN.md)
35-
- [Database Practice](/solution/DATABASE_README_EN.md)
34+
- [JavaScript](/solution/JAVASCRIPT_README_EN.md)
35+
- [Database](/solution/DATABASE_README_EN.md)
3636

3737
## Topics
3838

solution/0000-0099/0063.Unique Paths II/README.md

+103-34
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,13 @@ tags:
6565

6666
### 方法一:记忆化搜索
6767

68-
我们设计一个函数 $dfs(i, j)$ 表示从网格 $(i, j)$ 到网格 $(m - 1, n - 1)$ 的路径数。其中 $m$ 和 $n$ 分别是网格的行数和列数。
68+
我们设计一个函数 $\textit{dfs}(i, j)$ 表示从网格 $(i, j)$ 到网格 $(m - 1, n - 1)$ 的路径数。其中 $m$ 和 $n$ 分别是网格的行数和列数。
6969

70-
函数 $dfs(i, j)$ 的执行过程如下:
70+
函数 $\textit{dfs}(i, j)$ 的执行过程如下:
7171

72-
- 如果 $i \ge m$ 或者 $j \ge n$,或者 $obstacleGrid[i][j] = 1$,则路径数为 $0$;
72+
- 如果 $i \ge m$ 或者 $j \ge n$,或者 $\textit{obstacleGrid}[i][j] = 1$,则路径数为 $0$;
7373
- 如果 $i = m - 1$ 且 $j = n - 1$,则路径数为 $1$;
74-
- 否则,路径数为 $dfs(i + 1, j) + dfs(i, j + 1)$。
74+
- 否则,路径数为 $\textit{dfs}(i + 1, j) + \textit{dfs}(i, j + 1)$。
7575

7676
为了避免重复计算,我们可以使用记忆化搜索的方法。
7777

@@ -135,9 +135,8 @@ class Solution {
135135
public:
136136
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
137137
int m = obstacleGrid.size(), n = obstacleGrid[0].size();
138-
int f[m][n];
139-
memset(f, -1, sizeof(f));
140-
function<int(int, int)> dfs = [&](int i, int j) {
138+
vector<vector<int>> f(m, vector<int>(n, -1));
139+
auto dfs = [&](this auto&& dfs, int i, int j) {
141140
if (i >= m || j >= n || obstacleGrid[i][j]) {
142141
return 0;
143142
}
@@ -206,6 +205,64 @@ function uniquePathsWithObstacles(obstacleGrid: number[][]): number {
206205
}
207206
```
208207

208+
#### Rust
209+
210+
```rust
211+
impl Solution {
212+
pub fn unique_paths_with_obstacles(obstacle_grid: Vec<Vec<i32>>) -> i32 {
213+
let m = obstacle_grid.len();
214+
let n = obstacle_grid[0].len();
215+
let mut f = vec![vec![-1; n]; m];
216+
Self::dfs(0, 0, &obstacle_grid, &mut f)
217+
}
218+
219+
fn dfs(i: usize, j: usize, obstacle_grid: &Vec<Vec<i32>>, f: &mut Vec<Vec<i32>>) -> i32 {
220+
let m = obstacle_grid.len();
221+
let n = obstacle_grid[0].len();
222+
if i >= m || j >= n || obstacle_grid[i][j] == 1 {
223+
return 0;
224+
}
225+
if i == m - 1 && j == n - 1 {
226+
return 1;
227+
}
228+
if f[i][j] != -1 {
229+
return f[i][j];
230+
}
231+
let down = Self::dfs(i + 1, j, obstacle_grid, f);
232+
let right = Self::dfs(i, j + 1, obstacle_grid, f);
233+
f[i][j] = down + right;
234+
f[i][j]
235+
}
236+
}
237+
```
238+
239+
#### JavaScript
240+
241+
```js
242+
/**
243+
* @param {number[][]} obstacleGrid
244+
* @return {number}
245+
*/
246+
var uniquePathsWithObstacles = function (obstacleGrid) {
247+
const m = obstacleGrid.length;
248+
const n = obstacleGrid[0].length;
249+
const f = Array.from({ length: m }, () => Array(n).fill(-1));
250+
const dfs = (i, j) => {
251+
if (i >= m || j >= n || obstacleGrid[i][j] === 1) {
252+
return 0;
253+
}
254+
if (i === m - 1 && j === n - 1) {
255+
return 1;
256+
}
257+
if (f[i][j] === -1) {
258+
f[i][j] = dfs(i + 1, j) + dfs(i, j + 1);
259+
}
260+
return f[i][j];
261+
};
262+
return dfs(0, 0);
263+
};
264+
```
265+
209266
<!-- tabs:end -->
210267

211268
<!-- solution:end -->
@@ -214,12 +271,12 @@ function uniquePathsWithObstacles(obstacleGrid: number[][]): number {
214271

215272
### 方法二:动态规划
216273

217-
我们定义 $f[i][j]$ 表示到达网格 $(i,j)$ 的路径数。
274+
我们可以使用动态规划的方法,定义一个二维数组 $f$,其中 $f[i][j]$ 表示从网格 $(0,0)$ 到网格 $(i,j)$ 的路径数。
218275

219-
首先初始化 $f$ 第一列和第一行的所有值,然后遍历其它行和列,有两种情况:
276+
我们首先初始化 $f$ 的第一列和第一行的所有值,然后遍历其它行和列,有两种情况:
220277

221-
- 若 $obstacleGrid[i][j] = 1$,说明路径数为 $0$,那么 $f[i][j] = 0$;
222-
- 若 $obstacleGrid[i][j] = 0$,则 $f[i][j] = f[i - 1][j] + f[i][j - 1]$。
278+
- 若 $\textit{obstacleGrid}[i][j] = 1$,说明路径数为 $0$,那么 $f[i][j] = 0$;
279+
- 若 $\textit{obstacleGrid}[i][j] = 0$,则 $f[i][j] = f[i - 1][j] + f[i][j - 1]$。
223280

224281
最后返回 $f[m - 1][n - 1]$ 即可。
225282

@@ -357,29 +414,6 @@ function uniquePathsWithObstacles(obstacleGrid: number[][]): number {
357414
}
358415
```
359416

360-
#### TypeScript
361-
362-
```ts
363-
function uniquePathsWithObstacles(obstacleGrid: number[][]): number {
364-
const m = obstacleGrid.length;
365-
const n = obstacleGrid[0].length;
366-
const f: number[][] = Array.from({ length: m }, () => Array(n).fill(-1));
367-
const dfs = (i: number, j: number): number => {
368-
if (i >= m || j >= n || obstacleGrid[i][j] === 1) {
369-
return 0;
370-
}
371-
if (i === m - 1 && j === n - 1) {
372-
return 1;
373-
}
374-
if (f[i][j] === -1) {
375-
f[i][j] = dfs(i + 1, j) + dfs(i, j + 1);
376-
}
377-
return f[i][j];
378-
};
379-
return dfs(0, 0);
380-
}
381-
```
382-
383417
#### Rust
384418

385419
```rust
@@ -413,6 +447,41 @@ impl Solution {
413447
}
414448
```
415449

450+
#### JavaScript
451+
452+
```js
453+
/**
454+
* @param {number[][]} obstacleGrid
455+
* @return {number}
456+
*/
457+
var uniquePathsWithObstacles = function (obstacleGrid) {
458+
const m = obstacleGrid.length;
459+
const n = obstacleGrid[0].length;
460+
const f = Array.from({ length: m }, () => Array(n).fill(0));
461+
for (let i = 0; i < m; i++) {
462+
if (obstacleGrid[i][0] === 1) {
463+
break;
464+
}
465+
f[i][0] = 1;
466+
}
467+
for (let i = 0; i < n; i++) {
468+
if (obstacleGrid[0][i] === 1) {
469+
break;
470+
}
471+
f[0][i] = 1;
472+
}
473+
for (let i = 1; i < m; i++) {
474+
for (let j = 1; j < n; j++) {
475+
if (obstacleGrid[i][j] === 1) {
476+
continue;
477+
}
478+
f[i][j] = f[i - 1][j] + f[i][j - 1];
479+
}
480+
}
481+
return f[m - 1][n - 1];
482+
};
483+
```
484+
416485
<!-- tabs:end -->
417486

418487
<!-- solution:end -->

solution/0000-0099/0063.Unique Paths II/README_EN.md

+107-15
Original file line numberDiff line numberDiff line change
@@ -63,17 +63,17 @@ There are two ways to reach the bottom-right corner:
6363

6464
### Solution 1: Memoization Search
6565

66-
We design a function $dfs(i, j)$ to represent the number of paths from the grid $(i, j)$ to the grid $(m - 1, n - 1)$, where $m$ and $n$ are the number of rows and columns of the grid, respectively.
66+
We design a function $\textit{dfs}(i, j)$ to represent the number of paths from the grid $(i, j)$ to the grid $(m - 1, n - 1)$. Here, $m$ and $n$ are the number of rows and columns of the grid, respectively.
6767

68-
The execution process of the function $dfs(i, j)$ is as follows:
68+
The execution process of the function $\textit{dfs}(i, j)$ is as follows:
6969

70-
- If $i \ge m$ or $j \ge n$, or $obstacleGrid[i][j] = 1$, then the number of paths is $0$;
71-
- If $i = m - 1$ and $j = n - 1$, then the number of paths is $1$;
72-
- Otherwise, the number of paths is $dfs(i + 1, j) + dfs(i, j + 1)$.
70+
- If $i \ge m$ or $j \ge n$, or $\textit{obstacleGrid}[i][j] = 1$, the number of paths is $0$;
71+
- If $i = m - 1$ and $j = n - 1$, the number of paths is $1$;
72+
- Otherwise, the number of paths is $\textit{dfs}(i + 1, j) + \textit{dfs}(i, j + 1)$.
7373

74-
To avoid repeated calculations, we can use the method of memoization search.
74+
To avoid redundant calculations, we can use memoization.
7575

76-
The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Where $m$ and $n$ are the number of rows and columns of the grid, respectively.
76+
The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the number of rows and columns of the grid, respectively.
7777

7878
<!-- tabs:start -->
7979

@@ -133,9 +133,8 @@ class Solution {
133133
public:
134134
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
135135
int m = obstacleGrid.size(), n = obstacleGrid[0].size();
136-
int f[m][n];
137-
memset(f, -1, sizeof(f));
138-
function<int(int, int)> dfs = [&](int i, int j) {
136+
vector<vector<int>> f(m, vector<int>(n, -1));
137+
auto dfs = [&](this auto&& dfs, int i, int j) {
139138
if (i >= m || j >= n || obstacleGrid[i][j]) {
140139
return 0;
141140
}
@@ -204,6 +203,64 @@ function uniquePathsWithObstacles(obstacleGrid: number[][]): number {
204203
}
205204
```
206205

206+
#### Rust
207+
208+
```rust
209+
impl Solution {
210+
pub fn unique_paths_with_obstacles(obstacle_grid: Vec<Vec<i32>>) -> i32 {
211+
let m = obstacle_grid.len();
212+
let n = obstacle_grid[0].len();
213+
let mut f = vec![vec![-1; n]; m];
214+
Self::dfs(0, 0, &obstacle_grid, &mut f)
215+
}
216+
217+
fn dfs(i: usize, j: usize, obstacle_grid: &Vec<Vec<i32>>, f: &mut Vec<Vec<i32>>) -> i32 {
218+
let m = obstacle_grid.len();
219+
let n = obstacle_grid[0].len();
220+
if i >= m || j >= n || obstacle_grid[i][j] == 1 {
221+
return 0;
222+
}
223+
if i == m - 1 && j == n - 1 {
224+
return 1;
225+
}
226+
if f[i][j] != -1 {
227+
return f[i][j];
228+
}
229+
let down = Self::dfs(i + 1, j, obstacle_grid, f);
230+
let right = Self::dfs(i, j + 1, obstacle_grid, f);
231+
f[i][j] = down + right;
232+
f[i][j]
233+
}
234+
}
235+
```
236+
237+
#### JavaScript
238+
239+
```js
240+
/**
241+
* @param {number[][]} obstacleGrid
242+
* @return {number}
243+
*/
244+
var uniquePathsWithObstacles = function (obstacleGrid) {
245+
const m = obstacleGrid.length;
246+
const n = obstacleGrid[0].length;
247+
const f = Array.from({ length: m }, () => Array(n).fill(-1));
248+
const dfs = (i, j) => {
249+
if (i >= m || j >= n || obstacleGrid[i][j] === 1) {
250+
return 0;
251+
}
252+
if (i === m - 1 && j === n - 1) {
253+
return 1;
254+
}
255+
if (f[i][j] === -1) {
256+
f[i][j] = dfs(i + 1, j) + dfs(i, j + 1);
257+
}
258+
return f[i][j];
259+
};
260+
return dfs(0, 0);
261+
};
262+
```
263+
207264
<!-- tabs:end -->
208265

209266
<!-- solution:end -->
@@ -212,16 +269,16 @@ function uniquePathsWithObstacles(obstacleGrid: number[][]): number {
212269

213270
### Solution 2: Dynamic Programming
214271

215-
We define $f[i][j]$ as the number of paths to reach the grid $(i,j)$.
272+
We can use a dynamic programming approach by defining a 2D array $f$, where $f[i][j]$ represents the number of paths from the grid $(0,0)$ to the grid $(i,j)$.
216273

217-
First, initialize all values in the first column and first row of $f$. Then, traverse other rows and columns, there are two cases:
274+
We first initialize all values in the first column and the first row of $f$, then traverse the other rows and columns with two cases:
218275

219-
- If $obstacleGrid[i][j] = 1$, it means the number of paths is $0$, so $f[i][j] = 0$;
220-
- If $obstacleGrid[i][j] = 0$, then $f[i][j] = f[i - 1][j] + f[i][j - 1]$.
276+
- If $\textit{obstacleGrid}[i][j] = 1$, it means the number of paths is $0$, so $f[i][j] = 0$;
277+
- If $\textit{obstacleGrid}[i][j] = 0$, then $f[i][j] = f[i - 1][j] + f[i][j - 1]$.
221278

222279
Finally, return $f[m - 1][n - 1]$.
223280

224-
The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Where $m$ and $n$ are the number of rows and columns of the grid, respectively.
281+
The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$. Here, $m$ and $n$ are the number of rows and columns of the grid, respectively.
225282

226283
<!-- tabs:start -->
227284

@@ -388,6 +445,41 @@ impl Solution {
388445
}
389446
```
390447

448+
#### JavaScript
449+
450+
```js
451+
/**
452+
* @param {number[][]} obstacleGrid
453+
* @return {number}
454+
*/
455+
var uniquePathsWithObstacles = function (obstacleGrid) {
456+
const m = obstacleGrid.length;
457+
const n = obstacleGrid[0].length;
458+
const f = Array.from({ length: m }, () => Array(n).fill(0));
459+
for (let i = 0; i < m; i++) {
460+
if (obstacleGrid[i][0] === 1) {
461+
break;
462+
}
463+
f[i][0] = 1;
464+
}
465+
for (let i = 0; i < n; i++) {
466+
if (obstacleGrid[0][i] === 1) {
467+
break;
468+
}
469+
f[0][i] = 1;
470+
}
471+
for (let i = 1; i < m; i++) {
472+
for (let j = 1; j < n; j++) {
473+
if (obstacleGrid[i][j] === 1) {
474+
continue;
475+
}
476+
f[i][j] = f[i - 1][j] + f[i][j - 1];
477+
}
478+
}
479+
return f[m - 1][n - 1];
480+
};
481+
```
482+
391483
<!-- tabs:end -->
392484

393485
<!-- solution:end -->

solution/0000-0099/0063.Unique Paths II/Solution.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@ class Solution {
22
public:
33
int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
44
int m = obstacleGrid.size(), n = obstacleGrid[0].size();
5-
int f[m][n];
6-
memset(f, -1, sizeof(f));
7-
function<int(int, int)> dfs = [&](int i, int j) {
5+
vector<vector<int>> f(m, vector<int>(n, -1));
6+
auto dfs = [&](this auto&& dfs, int i, int j) {
87
if (i >= m || j >= n || obstacleGrid[i][j]) {
98
return 0;
109
}
@@ -18,4 +17,4 @@ class Solution {
1817
};
1918
return dfs(0, 0);
2019
}
21-
};
20+
};

0 commit comments

Comments
 (0)