当前位置: 首页 > news >正文

Kimi LeetCode 3459. 最长 V 形对角线段的长度 Java实现

LeetCode 3459. 最长 V 形对角线段的长度 — Java 实现

题目概述

- 给定 `n × m` 的矩阵 `grid`,元素值为 `0`、`1` 或 `2`。
- V 形对角线段 规则:
- 必须从 `1` 开始。
- 后续元素按 `2, 0, 2, 0, ...` 交替。
- 沿四个对角线方向之一移动。
- 最多允许一次顺时针 90° 转向。
- 返回最长合法路径的长度,不存在则返回 `0`。

---

核心思路:DFS + 记忆化搜索

状态定义:`memo[i][j][dir][turn]` 表示从位置 `(i, j)` 出发,当前移动方向为 `dir`,是否还能转向 `turn`(0/1)时,往后能延伸的最长路径长度。

四个对角方向(按顺时针排列):
- `0`: 右下 `(1, 1)`
- `1`: 左下 `(1, -1)`
- `2`: 左上 `(-1, -1)`
- `3`: 右上 `(-1, 1)`

顺时针 90° 转向:`dir → (dir + 1) % 4`

目标值计算:
- 当前值为 `1` → 下一步期望 `2`
- 当前值为 `2` → 下一步期望 `0`
- 当前值为 `0` → 下一步期望 `2`
- 统一公式:`next = grid[i][j] == 1 ? 2 : (2 - grid[i][j])`

递归逻辑:
1. 沿当前方向前进一步,检查是否越界且值匹配。
2. 选择一:继续直行。
3. 选择二:若还能转向,则顺时针转 90° 后继续。
4. 取两者最大值 + 1(当前步)。

---

Java 代码

```java
class Solution {
// 四个对角方向:右下、左下、左上、右上(顺时针排列)
private static final int[][] DIRS = {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}};

// 记忆化数组:memo[i][j][dir][turn]
// turn=1 表示还能转向,turn=0 表示已转过
private int[][][][] memo;
private int[][] grid;
private int m, n;

public int lenOfVDiagonal(int[][] grid) {
this.grid = grid;
this.m = grid.length;
this.n = grid[0].length;

// 初始化记忆化数组,-1 表示未计算
memo = new int[m][n][4][2];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
for (int d = 0; d < 4; d++) {
memo[i][j][d][0] = -1;
memo[i][j][d][1] = -1;
}
}
}

int ans = 0;
// 枚举所有起点(值为 1 的位置)
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
// 尝试四个初始方向
for (int d = 0; d < 4; d++) {
// +1 包含起点本身
ans = Math.max(ans, dfs(i, j, d, 1) + 1);
}
}
}
}
return ans;
}

/**
* 返回从 (i, j) 出发,沿方向 dir,是否还能转向 turn 时,
* 后续路径的最大长度(不包含当前点)
*/
private int dfs(int i, int j, int dir, int turn) {
// 计算下一步坐标
int ni = i + DIRS[dir][0];
int nj = j + DIRS[dir][1];

// 计算下一步期望值
int target = grid[i][j] == 1 ? 2 : (2 - grid[i][j]);

// 越界或值不匹配,路径终止
if (ni < 0 || ni >= m || nj < 0 || nj >= n || grid[ni][nj] != target) {
return 0;
}

// 检查记忆化
if (memo[ni][nj][dir][turn] != -1) {
return memo[ni][nj][dir][turn];
}

// 选择一:继续直行
int res = dfs(ni, nj, dir, turn);

// 选择二:若还能转向,顺时针转 90° 后继续
if (turn == 1) {
int turnRes = dfs(ni, nj, (dir + 1) % 4, 0);
res = Math.max(res, turnRes);
}

// 记忆化并返回(+1 包含当前步 ni,nj)
memo[ni][nj][dir][turn] = res + 1;
return res + 1;
}
}
```

---

复杂度分析

指标 复杂度 说明
时间 O(n × m × 4 × 2) = O(nm) 每个状态 `(i, j, dir, turn)` 只计算一次
空间 O(n × m × 4 × 2) = O(nm) 记忆化数组

---

验证示例

输入 输出 说明
`[[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` `(0,2)→(1,3)→(2,4)` 右转后 `(3,3)→(4,2)`
`[[2,2,2,2,2],[2,0,2,2,0],[2,0,1,1,0],[1,0,2,2,2],[2,0,0,2,2]]` `4` `(2,3)→(3,2)` 右转后 `(2,1)→(1,0)`
`[[1,2,2,2,2],[2,2,2,2,0],[2,0,0,0,0],[0,0,2,2,2],[2,0,0,2,0]]` `5` 不转向,直走 `(0,0)→(1,1)→(2,2)→(3,3)→(4,4)`
`[[1]]` `1` 只有起点

---

参考来源

- 灵茶山艾府题解中的记忆化搜索思路
- walkccc 题解中的 C++ 实现参考
- Progiez 的 Java 实现参考

http://www.jsqmd.com/news/1119367/

相关文章:

  • Grok-3与Claude 3.5 Sonnet真实能力对比分析
  • 4. 应用编程---进程
  • YOLO小样本学习与少样本目标检测:突破数据匮乏场景下的检测瓶颈
  • 大模型选型避坑指南:上下文衰减、结构化守约与真实成本测算
  • 西门子S7-1200与V90伺服PTO控制详解
  • TVA在具身智能商业化部署中的技术突破(15)
  • mori通信库分析(一)——对称内存RDMA数据发送过程
  • 工业物联架构:基于GPIO状态机的多品牌电梯物理调度架构设计
  • 淘宝电商运营新手入门完整教程|零基础开店引流
  • Bifrost:跨平台三星固件下载工具,5分钟轻松获取官方系统
  • Windows 11终极优化指南:开源工具Win11Debloat让你的系统快如闪电
  • java的if后面为什么需要加括号,而go却不需要呢?
  • 3个核心模块:如何快速掌握Blender MMD Tools的完整工作流
  • ptfe-article
  • GK7206V1:从AI ISP到芯片,一颗百元级深度学习降噪芯片的诞生(下)
  • ClassLoader深度解剖:双亲委派、Tomcat类隔离、SPI与模块化
  • 2024 VMware安装Ubuntu 24.04完整指南:避坑、优化与开发环境搭建
  • 《鬼谷八荒》2026硬核Mod全攻略安装教程
  • 【合作邀约】携手共创未来:专业试玩广告制作,赋能您的产品增长
  • 线上订单履约一体化:小程序同城配送与快递发货管理科普
  • 微信小程序开发学习文档(2026汇总版)
  • 毕设还剩 30 天?这份倒排计划表,照着做或直接找人做都来得及
  • 大模型版本命名误区解析:GPT-4o与DeepSeek-V2的真实能力边界
  • 基于51单片机智能窗帘系统—温湿度、光照、烟雾、定时、红外报警、手动、遥控
  • rk3588 适配 HDMI
  • 02-01-原理篇-Unity原生AssetBundle原理深度解析
  • 7 月 15 日起,追踪影视的 TV Time 应用停服,难盈利成主因
  • 警惕AI伪科技营销:GPT-5.5等虚构模型识别与事实核查指南
  • 【共创季稿事节】鸿蒙原生 ArkTS 布局方式之 Column 实现垂直时间轴组件:从 0 到 1 构建 Timeline UI
  • ChatGPT Plus值不值20美元?AI工具成本与效率深度拆解