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:
91101class 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
115126class 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-
159169class Solution {
160170public:
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
185207func 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