
2025-08-26:最长 V 形对角线段的长度。用go语言,给定一个 n × m 的整型矩阵,每个格子的值为 0、1 或 2。需要找出一种沿对角方向移动的连续格子路径,其规则如下:

在这里插入图片描述
要求返回满足上述条件的路径的最大长度(格子数量)。如果不存在任何符合条件的路径,则返回 0。
n == grid.length。
m == grid[i].length。
1 <= n, m <= 500。
grid[i][j] 的值为 0、1 或 2。
输入: grid = [[2,2,1,2,2],[2,0,2,2,0],[2,0,1,1,0],[1,0,2,2,2],[2,0,0,2,2]]。
输出: 5。
解释:

在这里插入图片描述
最长的 V 形对角线段长度为 5,路径如下:(0,2) → (1,3) → (2,4),在 (2,4) 处进行 顺时针 90 度转向 ,继续路径为 (3,3) → (4,2)。
题目来自力扣3459。
dirs = [4][2]int{{1,1}, {1,-1}, {-1,-1}, {-1,1}},分别对应东南、西南、西北、东北。memo,维度为[m][n][4][2]。其中:memo[i][j][d][t]表示从位置(i,j)出发,当前方向为d(0到3),且是否已经使用过转向(t=0表示未使用,t=1表示已使用)时,能获得的最大路径长度(包括当前格子)。memo所有值为-1,表示未计算。dfs(cx, cy, direction int, turn bool, target int) int(cx,cy):当前格子坐标。direction:当前移动方向(0到3)。turn:布尔值,表示是否已经使用过转向(true表示还可以转向,false表示已使用过?但注意:在调用中,初始时turn=true表示允许转向,而递归时若已转向则传入false)。target:下一个格子期望的值(根据交替规则:当前格子是1则下一个应为2;当前是2则下一个应为0;当前是0则下一个应为2)。(nx, ny)。
b. 检查边界:如果(nx,ny)越界或值不等于target,返回0(无法继续)。
c. 检查记忆数组:如果已计算过,直接返回结果。
d. 递归计算:
- 不转向:继续沿原方向移动,递归调用dfs(nx, ny, direction, turn, next_target)(其中next_target为2-target,因为0和2交替)。
- 如果允许转向(turn==true),则尝试顺时针旋转90度(即方向变为(direction+1)%4),并递归调用(传入turn=false表示已使用转向)。
e. 取两种选择的最大值,加1(当前格子)后存入记忆数组并返回。(i,j),如果值为1,则作为路径起点。dfs(i, j, direction, true, 2)(因为起点是1,下一个期望值是2)。(i, j, direction, turn)定义,共有m * n * 4 * 2 = 8*m*n个状态。每个状态计算时最多进行两次递归调用(不转向和转向),但实际由于记忆化,每个状态只计算一次。因此总时间复杂度为O(m*n)(因为常数因子8,但通常忽略),即与网格大小成线性。memo大小为m * n * 4 * 2,即8mn。递归深度最多为路径长度(但路径长度不会超过max(m,n),因此递归栈空间可忽略)。总额外空间为O(m*n)。总结:该算法通过记忆化DFS有效避免了重复计算,在网格问题上实现了线性时间复杂度和线性空间复杂度。
.
package main
import (
"fmt"
)
func lenOfVDiagonal(grid [][]int)int {
dirs := [4][2]int{{1, 1}, {1, -1}, {-1, -1}, {-1, 1}}
m, n := len(grid), len(grid[0])
memo := make([][][4][2]int, m)
for i := range memo {
memo[i] = make([][4][2]int, n)
for j := range memo[i] {
for k := range memo[i][j] {
for l := range memo[i][j][k] {
memo[i][j][k][l] = -1
}
}
}
}
var dfs func(cx, cy, direction int, turn bool, target int)int
dfs = func(cx, cy, direction int, turn bool, target int)int {
nx, ny := cx+dirs[direction][0], cy+dirs[direction][1]
/* 如果超出边界或者下一个节点值不是目标值,则返回 */
if nx < 0 || ny < 0 || nx >= m || ny >= n || grid[nx][ny] != target {
return0
}
turnInt := 0
if turn {
turnInt = 1
}
if memo[nx][ny][direction][turnInt] != -1 {
return memo[nx][ny][direction][turnInt]
}
/* 按照原来的方向继续行走 */
maxStep := dfs(nx, ny, direction, turn, 2-target)
if turn {
/* 顺时针旋转 90 度转向 */
maxStep = max(maxStep, dfs(nx, ny, (direction+1)%4, false, 2-target))
}
memo[nx][ny][direction][turnInt] = maxStep + 1
return maxStep + 1
}
res := 0
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if grid[i][j] == 1 {
for direction := 0; direction < 4; direction++ {
res = max(res, dfs(i, j, direction, true, 2)+1)
}
}
}
}
return res
}
func main() {
grid := [][]int{{2, 2, 1, 2, 2}, {2, 0, 2, 2, 0}, {2, 0, 1, 1, 0}, {1, 0, 2, 2, 2}, {2, 0, 0, 2, 2}}
result := lenOfVDiagonal(grid)
fmt.Println(result)
}

.
# -*-coding:utf-8-*-
import sys
sys.setrecursionlimit(10**6)
def lenOfVDiagonal(grid):
if not grid or not grid[0]:
return0
m, n = len(grid), len(grid[0])
dirs = [(1, 1), (1, -1), (-1, -1), (-1, 1)]
# memo[x][y][direction][turnInt],turnInt: 1 表示还可以转,0 表示已经转过
memo = [[[[ -1for _ in range(2)] for _ in range(4)] for _ in range(n)] for _ in range(m)]
def dfs(cx, cy, direction, turn, target):
nx = cx + dirs[direction][0]
ny = cy + dirs[direction][1]
# 越界或值不符合目标
if nx < 0 or ny < 0 or nx >= m or ny >= n or grid[nx][ny] != target:
return0
turnInt = 1if turn else0
if memo[nx][ny][direction][turnInt] != -1:
return memo[nx][ny][direction][turnInt]
# 继续沿原方向走
maxStep = dfs(nx, ny, direction, turn, 2 - target)
# 如果还可以转,则尝试顺时针转 90 度(direction+1)
if turn:
maxStep = max(maxStep, dfs(nx, ny, (direction + 1) % 4, False, 2 - target))
memo[nx][ny][direction][turnInt] = maxStep + 1
return memo[nx][ny][direction][turnInt]
res = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
for direction in range(4):
# dfs 从下一个格子开始计数,+1 把起点的 1 也算上
res = max(res, dfs(i, j, direction, True, 2) + 1)
return res
if __name__ == "__main__":
grid = [
[2, 2, 1, 2, 2],
[2, 0, 2, 2, 0],
[2, 0, 1, 1, 0],
[1, 0, 2, 2, 2],
[2, 0, 0, 2, 2],
]
print(lenOfVDiagonal(grid))
我们相信Go语言和算法为普通开发者提供了困境的“面试利器”,并致力于分享全面的编程知识。在这里,您可以找到最新的Go语言教程、算法解析、提升面试竞争力的秘籍以及行业动态。 欢迎关注“福大规模架构师每日一题”,让 Go 语言和算法助力您的职业发展