81
81
82
82
<!-- solution:start -->
83
83
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$ 分别是矩阵的行数和列数。
85
95
86
96
<!-- tabs:start -->
87
97
@@ -91,57 +101,60 @@ tags:
91
101
class Solution :
92
102
def hasValidPath (self , grid : List[List[str ]]) -> bool :
93
103
@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:
100
108
return False
101
109
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):
105
114
return True
106
115
return False
107
116
108
117
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
109
120
return dfs(0 , 0 , 0 )
110
121
```
111
122
112
123
#### Java
113
124
114
125
``` java
115
126
class Solution {
116
- private boolean [][][] vis ;
127
+ private int m, n ;
117
128
private char [][] grid;
118
- private int m;
119
- private int n;
129
+ private boolean [][][] vis;
120
130
121
131
public boolean hasValidPath (char [][] grid ) {
122
132
m = grid. length;
123
133
n = grid[0 ]. length;
134
+ if ((m + n - 1 ) % 2 == 1 || grid[0 ][0 ] == ' )' || grid[m - 1 ][n - 1 ] == ' (' ) {
135
+ return false ;
136
+ }
124
137
this . grid = grid;
125
138
vis = new boolean [m][n][m + n];
126
139
return dfs(0 , 0 , 0 );
127
140
}
128
141
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 ]) {
131
144
return false ;
132
145
}
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 ) {
136
149
return false ;
137
150
}
138
151
if (i == m - 1 && j == n - 1 ) {
139
- return t == 0 ;
152
+ return k == 0 ;
140
153
}
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 )) {
145
158
return true ;
146
159
}
147
160
}
@@ -153,28 +166,37 @@ class Solution {
153
166
#### C++
154
167
155
168
``` cpp
156
- bool vis[100 ][100 ][200 ];
157
- int dirs[3 ] = {1, 0, 1};
158
-
159
169
class Solution {
160
170
public:
161
171
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;
171
172
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;
176
175
}
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);
178
200
}
179
201
};
180
202
```
@@ -184,34 +206,37 @@ public:
184
206
```go
185
207
func hasValidPath(grid [][]byte) bool {
186
208
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
+ }
187
212
vis := make([][][]bool, m)
188
213
for i := range vis {
189
214
vis[i] = make([][]bool, n)
190
215
for j := range vis[i] {
191
216
vis[i][j] = make([]bool, m+n)
192
217
}
193
218
}
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] {
197
223
return false
198
224
}
199
- vis[i][j][t ] = true
225
+ vis[i][j][k ] = true
200
226
if grid[i][j] == '(' {
201
- t += 1
227
+ k++
202
228
} else {
203
- t -= 1
229
+ k--
204
230
}
205
- if t < 0 {
231
+ if k < 0 || k > m-i+n-j {
206
232
return false
207
233
}
208
234
if i == m-1 && j == n-1 {
209
- return t == 0
235
+ return k == 0
210
236
}
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) {
215
240
return true
216
241
}
217
242
}
@@ -221,6 +246,53 @@ func hasValidPath(grid [][]byte) bool {
221
246
}
222
247
```
223
248
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
+
224
296
<!-- tabs: end -->
225
297
226
298
<!-- solution: end -->
0 commit comments