@@ -114,65 +114,203 @@ tags:
114114
115115<!-- solution:start -->
116116
117- ### 方法一
117+ ### 方法一:记忆化搜索
118118
119- <!-- tabs:start -->
119+ 我们设计一个函数 $\text{dfs}(i, j, k, \textit{cnt})$,表示上一个位置为 $(i, j)$,当前方向为 $k$,剩余可转向次数为 $\textit{cnt}$ 时,返回最长的 V 形对角线段长度。
120120
121- #### Python3
121+ 函数 $\text{dfs}$ 的执行逻辑如下:
122122
123- ``` python
124- class Solution :
125- def lenOfVDiagonal (self , grid : List[List[int ]]) -> int :
126- m, n = len (grid), len (grid[0 ])
127- next_digit = {1 : 2 , 2 : 0 , 0 : 2 }
123+ 我们首先基于上一个位置以及当前的方向,计算当前得到当前位置 $(x, y)$,然后计算当前目标值 $\textit{target}$。如果 $x$ 或 $y$ 不在矩阵范围内,或者 $\textit{grid}[ x] [ y ] \neq \textit{target}$,返回 $0$。
128124
129- def within_bounds (i , j ):
130- return 0 <= i < m and 0 <= j < n
125+ 否则,我们有两种选择:
131126
132- @cache
133- def f (i , j , di , dj , turned ):
134- result = 1
135- successor = next_digit[grid[i][j]]
127+ 1 . 继续沿着当前方向前进。
128+ 2 . 在当前位置进行顺时针 90 度转向,然后继续前进。
129+
130+ 我们可以通过改变方向来实现顺时针 90 度转向。具体来说,如果当前方向为 $k$,则顺时针 90 度转向后的新方向为 $(k + 1) \bmod 4$。最后,我们选择这两种选择中的最大值作为当前状态的结果。
131+
132+ 在主函数中,我们遍历整个矩阵,对于每个值为 1 的位置,尝试四个方向的搜索,并更新答案。
133+
134+ 遍历结束后,返回答案即可。
136135
137- if within_bounds(i + di, j + dj) and grid[i + di][j + dj] == successor:
138- result = 1 + f(i + di, j + dj, di, dj, turned)
136+ 为了避免重复计算,我们使用记忆化搜索来缓存中间结果。
139137
140- if not turned:
141- di, dj = dj, - di
142- if within_bounds(i + di, j + dj) and grid[i + di][j + dj] == successor:
143- result = max (result, 1 + f(i + di, j + dj, di, dj, True ))
138+ 时间复杂度 $O(m \times n)$,空间复杂度 $O(m \times n)$。其中 $m$ 和 $n$ 分别是矩阵的行数和列数。
144139
145- return result
140+ <!-- tabs:start -->
146141
147- directions = ((1 , 1 ), (- 1 , 1 ), (1 , - 1 ), (- 1 , - 1 ))
148- result = 0
142+ #### Python3
149143
150- for i in range (m):
151- for j in range (n):
152- if grid[i][j] != 1 :
153- continue
154- for di, dj in directions:
155- result = max (result, f(i, j, di, dj, False ))
144+ ``` python
145+ class Solution :
146+ def lenOfVDiagonal (self , grid : List[List[int ]]) -> int :
147+ @cache
148+ def dfs (i : int , j : int , k : int , cnt : int ) -> int :
149+ x, y = i + dirs[k], j + dirs[k + 1 ]
150+ target = 2 if grid[i][j] == 1 else (2 - grid[i][j])
151+ if not 0 <= x < m or not 0 <= y < n or grid[x][y] != target:
152+ return 0
153+ res = dfs(x, y, k, cnt)
154+ if cnt > 0 :
155+ res = max (res, dfs(x, y, (k + 1 ) % 4 , 0 ))
156+ return 1 + res
156157
157- return result
158+ m, n = len (grid), len (grid[0 ])
159+ dirs = (1 , 1 , - 1 , - 1 , 1 )
160+ ans = 0
161+ for i, row in enumerate (grid):
162+ for j, x in enumerate (row):
163+ if x == 1 :
164+ for k in range (4 ):
165+ ans = max (ans, dfs(i, j, k, 1 ) + 1 )
166+ return ans
158167```
159168
160169#### Java
161170
162171``` java
163-
172+ class Solution {
173+ private int m, n;
174+ private final int [] dirs = {1 , 1 , - 1 , - 1 , 1 };
175+ private Integer [][][][] f;
176+
177+ public int lenOfVDiagonal (int [][] grid ) {
178+ m = grid. length;
179+ n = grid[0 ]. length;
180+ f = new Integer [m][n][4 ][2 ];
181+ int ans = 0 ;
182+ for (int i = 0 ; i < m; i++ ) {
183+ for (int j = 0 ; j < n; j++ ) {
184+ if (grid[i][j] == 1 ) {
185+ for (int k = 0 ; k < 4 ; k++ ) {
186+ ans = Math . max(ans, dfs(grid, i, j, k, 1 ) + 1 );
187+ }
188+ }
189+ }
190+ }
191+ return ans;
192+ }
193+
194+ private int dfs (int [][] grid , int i , int j , int k , int cnt ) {
195+ if (f[i][j][k][cnt] != null ) {
196+ return f[i][j][k][cnt];
197+ }
198+ int x = i + dirs[k];
199+ int y = j + dirs[k + 1 ];
200+ int target = grid[i][j] == 1 ? 2 : (2 - grid[i][j]);
201+ if (x < 0 || x >= m || y < 0 || y >= n || grid[x][y] != target) {
202+ f[i][j][k][cnt] = 0 ;
203+ return 0 ;
204+ }
205+ int res = dfs(grid, x, y, k, cnt);
206+ if (cnt > 0 ) {
207+ res = Math . max(res, dfs(grid, x, y, (k + 1 ) % 4 , 0 ));
208+ }
209+ f[i][j][k][cnt] = 1 + res;
210+ return 1 + res;
211+ }
212+ }
164213```
165214
166215#### C++
167216
168217``` cpp
169-
218+ class Solution {
219+ public:
220+ static constexpr int MAXN = 501;
221+ int f[ MAXN] [ MAXN ] [ 4] [ 2 ] ;
222+
223+ int lenOfVDiagonal(vector<vector<int>>& grid) {
224+ int m = grid.size(), n = grid[0].size();
225+ int dirs[5] = {1, 1, -1, -1, 1};
226+ memset(f, -1, sizeof(f));
227+
228+ auto dfs = [&](this auto&& dfs, int i, int j, int k, int cnt) -> int {
229+ if (f[i][j][k][cnt] != -1) {
230+ return f[i][j][k][cnt];
231+ }
232+ int x = i + dirs[k];
233+ int y = j + dirs[k + 1 ];
234+ int target = grid[i][j] == 1 ? 2 : (2 - grid[i][j]);
235+ if (x < 0 || x >= m || y < 0 || y >= n || grid[x][y] != target) {
236+ f[i][j][k][cnt] = 0;
237+ return 0;
238+ }
239+ int res = dfs(x, y, k, cnt);
240+ if (cnt > 0) {
241+ res = max(res, dfs(x, y, (k + 1) % 4, 0));
242+ }
243+ f[i][j][k][cnt] = 1 + res;
244+ return 1 + res;
245+ };
246+
247+ int ans = 0;
248+ for (int i = 0; i < m; ++i) {
249+ for (int j = 0; j < n; ++j) {
250+ if (grid[i][j] == 1) {
251+ for (int k = 0; k < 4; ++k) {
252+ ans = max(ans, dfs(i, j, k, 1) + 1);
253+ }
254+ }
255+ }
256+ }
257+ return ans;
258+ }
259+ };
170260```
171261
172262#### Go
173263
174264``` go
175-
265+ func lenOfVDiagonal (grid [][]int ) int {
266+ m , n := len (grid), len (grid[0 ])
267+ dirs := []int {1 , 1 , -1 , -1 , 1 }
268+ f := make ([][][4 ][2 ]int , m)
269+ for i := range f {
270+ f[i] = make ([][4 ][2 ]int , n)
271+ }
272+
273+ var dfs func (i, j, k, cnt int ) int
274+ dfs = func (i, j, k, cnt int ) int {
275+ if f[i][j][k][cnt] != 0 {
276+ return f[i][j][k][cnt]
277+ }
278+
279+ x := i + dirs[k]
280+ y := j + dirs[k+1 ]
281+
282+ var target int
283+ if grid[i][j] == 1 {
284+ target = 2
285+ } else {
286+ target = 2 - grid[i][j]
287+ }
288+
289+ if x < 0 || x >= m || y < 0 || y >= n || grid[x][y] != target {
290+ f[i][j][k][cnt] = 0
291+ return 0
292+ }
293+
294+ res := dfs (x, y, k, cnt)
295+ if cnt > 0 {
296+ res = max (res, dfs (x, y, (k+1 )%4 , 0 ))
297+ }
298+ f[i][j][k][cnt] = res + 1
299+ return res + 1
300+ }
301+
302+ ans := 0
303+ for i := 0 ; i < m; i++ {
304+ for j := 0 ; j < n; j++ {
305+ if grid[i][j] == 1 {
306+ for k := 0 ; k < 4 ; k++ {
307+ ans = max (ans, dfs (i, j, k, 1 )+1 )
308+ }
309+ }
310+ }
311+ }
312+ return ans
313+ }
176314```
177315
178316<!-- tabs:end -->
0 commit comments