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

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

以下是 LeetCode 3459「最长 V 形对角线段的长度」的 C 语言实现。

解题思路

核心算法:记忆化搜索 (DFS + Memoization)

- 状态定义:`memo[i][j][dir][turn]` 表示从坐标 `(i,j)` 出发,当前移动方向为 `dir`,是否还能右转(`turn`)的情况下,后续路径的最大长度。
- 四个对角方向(按顺时针排列):
- `dir=0`: (1, 1) 右下
- `dir=1`: (1, -1) 左下
- `dir=2`: (-1, -1) 左上
- `dir=3`: (-1, 1) 右上
- 顺时针90度右转:`(dir + 1) % 4`
- 序列模式:`1 → 2 → 0 → 2 → 0 → ...`,下一个目标值用 `2 - target` 计算

复杂度:
- 时间:O(n × m × 4 × 2) = O(n × m)
- 空间:O(n × m × 4 × 2) = O(n × m)

---

C 代码

```c
#include <stdlib.h>

/**
* LeetCode 3459. 最长 V 形对角线段的长度 - C语言实现
* =====================================================
*
* 题目要求:
* 在 n x m 的矩阵中,找最长的 V 形对角线段。
* - 起点必须是 1
* - 后续值按 2, 0, 2, 0, ... 交替
* - 沿对角线方向移动
* - 最多允许一次顺时针 90 度转向
*
* 算法:记忆化搜索 (DFS + Memoization)
*/

// 四个对角方向(按顺时针排列):右下、左下、左上、右上
static const int DIRS[4][2] = {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}};

// 扁平化访问记忆化数组:memo[i][j][dir][turn]
// 索引计算:(i * n + j) * 8 + dir * 2 + turn
static inline int* get_memo(int *memo, int n, int i, int j, int dir, int turn) {
return &memo[(i * n + j) * 8 + dir * 2 + turn];
}

/**
* DFS 搜索从 (i,j) 沿方向 dir 前进,期望值为 target 的最长路径
* @param turn: 1 表示还可以右转,0 表示已经转过或不能转
* @return: 从下一个合法格子开始的路径长度(不含当前(i,j))
*/
int dfs(int **grid, int *memo, int m, int n, int i, int j, int dir, int turn, int target) {
int ni = i + DIRS[dir][0];
int nj = j + DIRS[dir][1];

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

// 查记忆化表
int *p = get_memo(memo, n, ni, nj, dir, turn);
if (*p != 0) {
return *p;
}

int next_target = 2 - target; // 2->0, 0->2

// 选择1:继续沿当前方向直行
int res = dfs(grid, memo, m, n, ni, nj, dir, turn, next_target) + 1;

// 选择2:如果还能右转,顺时针90度转向(dir -> (dir+1)%4)
if (turn) {
int turn_res = dfs(grid, memo, m, n, ni, nj, (dir + 1) % 4, 0, next_target) + 1;
if (turn_res > res) {
res = turn_res;
}
}

*p = res;
return res;
}

int lenOfVDiagonal(int** grid, int gridSize, int* gridColSize) {
int m = gridSize;
int n = gridColSize[0];

if (m == 0 || n == 0) {
return 0;
}

// 分配并初始化记忆化数组(全部置0)
// 每个格子8种状态:4方向 x 2种turn状态
int *memo = (int *)calloc(m * n * 8, sizeof(int));

int ans = 0;

// 遍历所有可能的起点
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// 起点必须是 1
if (grid[i][j] != 1) {
continue;
}

// 尝试四个初始方向
for (int dir = 0; dir < 4; dir++) {
// dfs返回从(i,j)之后的路径长度,+1包含起点本身
int len = dfs(grid, memo, m, n, i, j, dir, 1, 2) + 1;
if (len > ans) {
ans = len;
}
}
}
}

free(memo);
return ans;
}
```

---

关键要点说明

要点 说明
方向数组顺序 必须按顺时针排列 `(右下→左下→左上→右上)`,这样 `(dir+1)%4` 才是正确的顺时针90度转向
目标值交替 `next_target = 2 - target` 巧妙实现 `2↔0` 交替
记忆化状态 每个格子 8 种状态(4方向 × 2种turn),用扁平化数组存储减少分配开销
起点处理 只有值为 `1` 的格子才能作为起点,初始目标值固定为 `2`

下载文件:[leetcode_3459.c](sandbox:///mnt/agents/output/leetcode_3459.c)

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

相关文章:

  • 终极UE4SS实战指南:如何无需源码深度定制Unreal Engine游戏
  • FORCE_PROMPT_CACHING_5M,Claude Code 缓存 TTL 的刹车踏板
  • 5个实用的Google Cloud Vision API示例项目详解
  • 个人分享|校园新闻网站源码与配套论文,课设毕设参考素材!
  • 黑苹果配置革命:OpCore Simplify - 自动化EFI生成终极解决方案
  • CTF Web安全入门:三个月系统学习路线与实战技巧
  • 解决Obsidian中嵌入Claude Code的问题
  • ICM-42688-P与PIC18LF27K42在工业振动监测中的优化应用
  • Lua 5.1字节码反编译终极指南:luadec51完整使用教程
  • 3. 应用编程---信号
  • 大模型能力对比:基于场景锚点的AI选型方法论
  • OpenCore Legacy Patcher完整指南:让老款Mac免费升级最新macOS的终极方案
  • Deepin Boot Maker终极指南:3步制作Linux启动盘的最佳实践
  • 林伽一 · AI科技日报 |LongCat-2.0宣称中国芯片突破,Claude Sonnet 5自报分数解析
  • ComfyUI-WanVideoWrapper实现AI视频生成性能突破:径向注意力与FP8量化技术深度解析
  • 终极指南:3分钟学会用FanControl掌控Windows电脑风扇,告别噪音烦恼
  • “写了十年代码,我才懂什么叫“一即一切“:分形几何×七境修心,一个程序员的自救指南
  • Linux高并发Reactor反应堆模式深度精讲,单Reactor、多Reactor架构、epoll高并发服务器手写、Nginx核心架构落地实战
  • Python cryptography库实战:RSA非对称加密与数字签名完整指南
  • 3分钟掌握Diablo Edit2:暗黑2存档修改器的终极解决方案
  • The Other Side of the Grail: Risks to the Mission System and the Complete Solution
  • 赋值操作符:=和复合赋值
  • 2026图片去水印怎么弄?无痕去水印实用技巧+免费工具手机电脑教程
  • 用 AI 写代码做家庭调酒小程序:真正难的是把酒库到保存跑通
  • ClaudeMax实战压测:什么场景下它才不可替代?
  • 质量门脚本:用Python给AI输出加上自动质检(附完整源码)
  • Azure Local离线模式身份规划(系列篇之三)
  • JVM是什么?
  • 良心盘点!2026AI论文写作工具榜单(覆盖 99% 学生论文写作需求)
  • YOLOv13超图视觉与NCNN部署实战指南