Skip to content

Commit 5f64a77

Browse files
authored
feat: add solutions to lc problem: No.2267 (doocs#3726)
No.2267.Check if There Is a Valid Parentheses String Path
1 parent f769732 commit 5f64a77

File tree

7 files changed

+359
-158
lines changed

7 files changed

+359
-158
lines changed

solution/2200-2299/2267.Check if There Is a Valid Parentheses String Path/README.md

+124-52
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,17 @@ tags:
8181

8282
<!-- solution:start -->
8383

84-
### 方法一:记忆化搜索
84+
### 方法一:DFS + 剪枝
85+
86+
我们记矩阵的行数为 $m$,列数为 $n$。
87+
88+
如果 $m + n - 1$ 为奇数,或者左上角和右下角的括号不匹配,那么一定不存在合法路径,直接返回 $\text{false}$。
89+
90+
否则,我们设计一个函数 $\textit{dfs}(i, j, k)$,表示从 $(i, j)$ 出发,且当前括号的平衡度为 $k$,是否存在合法路径。其中,平衡度 $k$ 的定义为:从 $(0, 0)$ 到 $(i, j)$ 的路径中,左括号的个数减去右括号的个数。
91+
92+
如果平衡度 $k$ 小于 $0$ 或者大于 $m + n - i - j$,那么一定不存在合法路径,直接返回 $\text{false}$。如果 $(i, j)$ 正好是右下角的格子,那么只有当 $k = 0$ 时才存在合法路径。否则,我们枚举 $(i, j)$ 的下一个格子 $(x, y)$,如果 $(x, y)$ 是合法的格子且 $\textit{dfs}(x, y, k)$ 为 $\text{true}$,那么就存在合法路径。
93+
94+
时间复杂度 $O(m \times n \times (m + n))$,空间复杂度 $O(m \times n \times (m + n))$。其中 $m$ 和 $n$ 分别是矩阵的行数和列数。
8595

8696
<!-- tabs:start -->
8797

@@ -91,57 +101,60 @@ tags:
91101
class Solution:
92102
def hasValidPath(self, grid: List[List[str]]) -> bool:
93103
@cache
94-
def dfs(i, j, t):
95-
if grid[i][j] == '(':
96-
t += 1
97-
else:
98-
t -= 1
99-
if t < 0:
104+
def dfs(i: int, j: int, k: int) -> bool:
105+
d = 1 if grid[i][j] == "(" else -1
106+
k += d
107+
if k < 0 or k > m - i + n - j:
100108
return False
101109
if i == m - 1 and j == n - 1:
102-
return t == 0
103-
for x, y in [(i + 1, j), (i, j + 1)]:
104-
if x < m and y < n and dfs(x, y, t):
110+
return k == 0
111+
for a, b in pairwise((0, 1, 0)):
112+
x, y = i + a, j + b
113+
if 0 <= x < m and 0 <= y < n and dfs(x, y, k):
105114
return True
106115
return False
107116

108117
m, n = len(grid), len(grid[0])
118+
if (m + n - 1) % 2 or grid[0][0] == ")" or grid[m - 1][n - 1] == "(":
119+
return False
109120
return dfs(0, 0, 0)
110121
```
111122

112123
#### Java
113124

114125
```java
115126
class Solution {
116-
private boolean[][][] vis;
127+
private int m, n;
117128
private char[][] grid;
118-
private int m;
119-
private int n;
129+
private boolean[][][] vis;
120130

121131
public boolean hasValidPath(char[][] grid) {
122132
m = grid.length;
123133
n = grid[0].length;
134+
if ((m + n - 1) % 2 == 1 || grid[0][0] == ')' || grid[m - 1][n - 1] == '(') {
135+
return false;
136+
}
124137
this.grid = grid;
125138
vis = new boolean[m][n][m + n];
126139
return dfs(0, 0, 0);
127140
}
128141

129-
private boolean dfs(int i, int j, int t) {
130-
if (vis[i][j][t]) {
142+
private boolean dfs(int i, int j, int k) {
143+
if (vis[i][j][k]) {
131144
return false;
132145
}
133-
vis[i][j][t] = true;
134-
t += grid[i][j] == '(' ? 1 : -1;
135-
if (t < 0) {
146+
vis[i][j][k] = true;
147+
k += grid[i][j] == '(' ? 1 : -1;
148+
if (k < 0 || k > m - i + n - j) {
136149
return false;
137150
}
138151
if (i == m - 1 && j == n - 1) {
139-
return t == 0;
152+
return k == 0;
140153
}
141-
int[] dirs = {0, 1, 0};
142-
for (int k = 0; k < 2; ++k) {
143-
int x = i + dirs[k], y = j + dirs[k + 1];
144-
if (x < m && y < n && dfs(x, y, t)) {
154+
final int[] dirs = {1, 0, 1};
155+
for (int d = 0; d < 2; ++d) {
156+
int x = i + dirs[d], y = j + dirs[d + 1];
157+
if (x >= 0 && x < m && y >= 0 && y < n && dfs(x, y, k)) {
145158
return true;
146159
}
147160
}
@@ -153,28 +166,37 @@ class Solution {
153166
#### C++
154167

155168
```cpp
156-
bool vis[100][100][200];
157-
int dirs[3] = {1, 0, 1};
158-
159169
class Solution {
160170
public:
161171
bool hasValidPath(vector<vector<char>>& grid) {
162-
memset(vis, 0, sizeof(vis));
163-
return dfs(0, 0, 0, grid);
164-
}
165-
166-
bool dfs(int i, int j, int t, vector<vector<char>>& grid) {
167-
if (vis[i][j][t]) return false;
168-
vis[i][j][t] = true;
169-
t += grid[i][j] == '(' ? 1 : -1;
170-
if (t < 0) return false;
171172
int m = grid.size(), n = grid[0].size();
172-
if (i == m - 1 && j == n - 1) return t == 0;
173-
for (int k = 0; k < 2; ++k) {
174-
int x = i + dirs[k], y = j + dirs[k + 1];
175-
if (x < m && y < n && dfs(x, y, t, grid)) return true;
173+
if ((m + n - 1) % 2 || grid[0][0] == ')' || grid[m - 1][n - 1] == '(') {
174+
return false;
176175
}
177-
return false;
176+
bool vis[m][n][m + n];
177+
memset(vis, false, sizeof(vis));
178+
int dirs[3] = {1, 0, 1};
179+
auto dfs = [&](auto&& dfs, int i, int j, int k) -> bool {
180+
if (vis[i][j][k]) {
181+
return false;
182+
}
183+
vis[i][j][k] = true;
184+
k += grid[i][j] == '(' ? 1 : -1;
185+
if (k < 0 || k > m - i + n - j) {
186+
return false;
187+
}
188+
if (i == m - 1 && j == n - 1) {
189+
return k == 0;
190+
}
191+
for (int d = 0; d < 2; ++d) {
192+
int x = i + dirs[d], y = j + dirs[d + 1];
193+
if (x >= 0 && x < m && y >= 0 && y < n && dfs(dfs, x, y, k)) {
194+
return true;
195+
}
196+
}
197+
return false;
198+
};
199+
return dfs(dfs, 0, 0, 0);
178200
}
179201
};
180202
```
@@ -184,34 +206,37 @@ public:
184206
```go
185207
func hasValidPath(grid [][]byte) bool {
186208
m, n := len(grid), len(grid[0])
209+
if (m+n-1)%2 == 1 || grid[0][0] == ')' || grid[m-1][n-1] == '(' {
210+
return false
211+
}
187212
vis := make([][][]bool, m)
188213
for i := range vis {
189214
vis[i] = make([][]bool, n)
190215
for j := range vis[i] {
191216
vis[i][j] = make([]bool, m+n)
192217
}
193218
}
194-
var dfs func(int, int, int) bool
195-
dfs = func(i, j, t int) bool {
196-
if vis[i][j][t] {
219+
dirs := [3]int{1, 0, 1}
220+
var dfs func(i, j, k int) bool
221+
dfs = func(i, j, k int) bool {
222+
if vis[i][j][k] {
197223
return false
198224
}
199-
vis[i][j][t] = true
225+
vis[i][j][k] = true
200226
if grid[i][j] == '(' {
201-
t += 1
227+
k++
202228
} else {
203-
t -= 1
229+
k--
204230
}
205-
if t < 0 {
231+
if k < 0 || k > m-i+n-j {
206232
return false
207233
}
208234
if i == m-1 && j == n-1 {
209-
return t == 0
235+
return k == 0
210236
}
211-
dirs := []int{1, 0, 1}
212-
for k := 0; k < 2; k++ {
213-
x, y := i+dirs[k], j+dirs[k+1]
214-
if x < m && y < n && dfs(x, y, t) {
237+
for d := 0; d < 2; d++ {
238+
x, y := i+dirs[d], j+dirs[d+1]
239+
if x >= 0 && x < m && y >= 0 && y < n && dfs(x, y, k) {
215240
return true
216241
}
217242
}
@@ -221,6 +246,53 @@ func hasValidPath(grid [][]byte) bool {
221246
}
222247
```
223248

249+
#### TypeScript
250+
251+
```ts
252+
function hasValidPath(grid: string[][]): boolean {
253+
const m = grid.length,
254+
n = grid[0].length;
255+
256+
if ((m + n - 1) % 2 || grid[0][0] === ')' || grid[m - 1][n - 1] === '(') {
257+
return false;
258+
}
259+
260+
const vis: boolean[][][] = Array.from({ length: m }, () =>
261+
Array.from({ length: n }, () => Array(m + n).fill(false)),
262+
);
263+
const dirs = [1, 0, 1];
264+
265+
const dfs = (i: number, j: number, k: number): boolean => {
266+
if (vis[i][j][k]) {
267+
return false;
268+
}
269+
270+
vis[i][j][k] = true;
271+
k += grid[i][j] === '(' ? 1 : -1;
272+
273+
if (k < 0 || k > m - i + n - j) {
274+
return false;
275+
}
276+
277+
if (i === m - 1 && j === n - 1) {
278+
return k === 0;
279+
}
280+
281+
for (let d = 0; d < 2; ++d) {
282+
const x = i + dirs[d],
283+
y = j + dirs[d + 1];
284+
if (x >= 0 && x < m && y >= 0 && y < n && dfs(x, y, k)) {
285+
return true;
286+
}
287+
}
288+
289+
return false;
290+
};
291+
292+
return dfs(0, 0, 0);
293+
}
294+
```
295+
224296
<!-- tabs:end -->
225297

226298
<!-- solution:end -->

0 commit comments

Comments
 (0)