每日一题——矩阵最长递增路径

矩阵最长递增路径问题

      • 题目描述
      • 数据范围:
      • 进阶要求:
      • 示例
        • 示例 1
        • 示例 2
      • 题解思路
      • 算法步骤:
      • 代码实现
      • 代码解释
      • 复杂度分析
      • 总结

题目描述

给定一个 n 行 m 列的矩阵 matrix,矩阵内所有数均为非负整数。你需要在矩阵中找到一条最长路径,使得这条路径上的元素是递增的。并输出这条最长路径的长度。

该路径必须满足以下条件:

  1. 对于每个单元格,你可以往上、下、左、右四个方向移动。不能在对角线方向上移动或移动到边界外。
  2. 你不能走重复的单元格。即每个格子最多只能走一次。

数据范围:

  • 1 ≤ n, m ≤ 1000
  • 0 ≤ matrix[i][j] ≤ 1000
    在这里插入图片描述

进阶要求:

  • 空间复杂度:O(nm)
  • 时间复杂度:O(nm)

示例

示例 1

输入

[[1,2,3],[4,5,6],[7,8,9]]

返回值

5

说明
最长递增路径为:1 -> 2 -> 3 -> 6 -> 9

示例 2

输入

[[1,2],[4,3]]

返回值

4

说明
最长递增路径为:1 -> 2 -> 3 -> 4

题解思路

这个问题可以通过 深度优先搜索(DFS)结合 动态规划(DP)来高效地解决。关键思路是:

  1. 深度优先搜索(DFS):我们可以对每个元素进行深度优先搜索,查找从该元素出发的最长递增路径。
  2. 动态规划(DP):我们可以在 DFS 搜索的过程中利用动态规划来避免重复计算相同位置的路径长度,从而提高效率。

算法步骤:

  1. 初始化

    • 创建一个 dp 数组,记录每个位置的最长递增路径长度。
    • 遍历每个单元格,使用 DFS 算法寻找每个单元格的最长路径。
  2. DFS 搜索

    • 对每个位置 (i, j),判断其四个邻接位置(上、下、左、右),如果邻接位置的值大于当前值,则递归搜索该邻接位置。
    • 使用 dp[i][j] 存储从 (i, j) 出发的最长递增路径,避免重复计算。
  3. 结果

    • 在遍历所有单元格后,dp 数组中的最大值即为矩阵中的最长递增路径。

代码实现


#include <stdio.h>
#include <stdlib.h>// 定义方向数组,表示上下左右四个方向
int directions[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};/*** 深度优先搜索(DFS)函数,用于计算从 (x, y) 开始的最长递增路径* * @param matrix 二维数组,表示矩阵* @param x 当前位置的行索引* @param y 当前位置的列索引* @param m 矩阵的行数* @param n 矩阵的列数* @param count 当前路径的长度* @return 从 (x, y) 开始的最长递增路径长度*/
int dfs(int** matrix, int x, int y, int m, int n, int count) {// 如果超出矩阵边界,返回当前路径长度if (x < 0 || x >= m || y < 0 || y >= n) {return count;}int maxPath = count; // 初始化当前最大路径长度为当前路径长度// 遍历四个方向for (int i = 0; i < 4; i++) {int nx = x + directions[i][0]; // 计算相邻位置的行索引int ny = y + directions[i][1]; // 计算相邻位置的列索引// 如果相邻位置超出矩阵边界,跳过if (nx < 0 || nx >= m || ny < 0 || ny >= n) {continue;}// 如果相邻位置的值小于当前位置的值,说明可以继续递增if (matrix[nx][ny] < matrix[x][y]) {// 递归调用 dfs,计算从相邻位置开始的路径长度int temp = dfs(matrix, nx, ny, m, n, count + 1);// 更新最大路径长度maxPath = maxPath > temp ? maxPath : temp;}}return maxPath; // 返回从 (x, y) 开始的最长递增路径长度
}/*** 主函数,计算矩阵中的最长递增路径* * @param matrix 二维数组,表示矩阵* @param matrixRowLen 矩阵的行数* @param matrixColLen 矩阵的列数* @return 矩阵中的最长递增路径长度*/
int solve(int** matrix, int matrixRowLen, int* matrixColLen) {// 如果矩阵为空或行数为0,返回0if (matrixRowLen == 0 || matrix == NULL) {return 0;}int m = matrixRowLen; // 矩阵的行数int n = matrixColLen[0]; // 矩阵的列数int maxLength = 0; // 初始化最长递增路径长度为0// 遍历矩阵的每个位置for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {// 从每个位置调用 dfs,计算从该位置开始的最长递增路径int pathLength = dfs(matrix, i, j, m, n, 1);// 更新最长递增路径的长度maxLength = maxLength > pathLength ? maxLength : pathLength;}}return maxLength; // 返回矩阵中的最长递增路径长度
}// 测试函数
int main() {// 定义一个示例矩阵int matrix[4][4] = {{9, 9, 4, 5},{6, 6, 8, 7},{2, 1, 1, 3},{3, 4, 2, 1}};int m = 4; // 矩阵的行数int n = 4; // 矩阵的列数// 将二维数组转换为指针数组int* matrixPtr[4];for (int i = 0; i < m; i++) {matrixPtr[i] = matrix[i];}// 定义列数数组int matrixColLen[4] = {n, n, n, n};// 调用 solve 函数,计算最长递增路径int maxLength = solve(matrixPtr, m, matrixColLen);// 打印结果printf("The longest increasing path length is: %d\n", maxLength);return 0;
}

代码解释

  1. dp 数组初始化dp 数组用于记录从每个单元格出发的最长递增路径。初始化时设置为 -1,表示该位置尚未计算过。

  2. DFS 函数

    • dfs(i, j) 是递归函数,用于计算从位置 (i, j) 开始的最长递增路径。
    • 首先检查 dp[i][j] 是否已经计算过,如果计算过,则直接返回 dp[i][j]
    • 否则,初始化最长路径为 1,即当前位置本身。
    • 对于当前位置 (i, j),检查其四个邻接位置,如果邻接位置的值大于当前值,则递归计算该邻接位置的最长路径,并更新当前路径长度。
    • 最终返回 dp[i][j]
  3. 主函数

    • 遍历整个矩阵,对每个位置调用 dfs 函数,并更新最大路径长度 max_path
    • 最终返回最大路径长度。

复杂度分析

  1. 时间复杂度O(nm),每个位置最多计算一次。递归时,通过 dp 数组避免了重复计算。

  2. 空间复杂度O(nm),需要一个 dp 数组来存储每个位置的最长递增路径长度。

总结

这个问题使用 DFS 和动态规划的结合来有效地求解,避免了重复计算,提高了性能。通过合理使用 np 数组,我们可以确保每个位置的最长路径只计算一次,从而将时间复杂度降低到线性级别。
这题整体难度一般,和之前的求岛屿数量完全类似。但是仔细想想还是要多多注意,比如它还是要遍历整个数组,因为从任何路径走都是有可能的。另外幸好是单调递增,如果是单调非减的话就麻烦很多,因为单调非减会不停来回震荡,就很麻烦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/21543.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vscode 配置 Copilot 提示GHE.com连接失败

步骤一&#xff1a;打开设置并进入 settings.json 点击菜单栏中的 “文件” -> “首选项” -> “设置”。 在搜索设置栏中输入 “Copilot: Advanced”。 点击搜索结果下方的 “在 settings.json 中编辑” 链接&#xff0c;这会打开 settings.json 文件。 步骤二&#…

DEX-EE三指灵巧手:扩展AI与机器人研究的边界

DEX-EE三指灵巧手&#xff0c;由Shadow Robot与Google DeepMind合作开发&#xff0c;以其先进技术和设计&#xff0c;正在引领AI与机器人研究的新趋势。其高精度传感器和灵活的机械手指&#xff0c;能够捕捉复杂的环境数据&#xff0c;为强化学习实验提供了可靠支持。 Shadow R…

cornerstone3D学习笔记-MPR

最近在研究如何利用cornerstone3D (v1.70.13) 来实现MPR功能&#xff0c;找到它的一个demo -- volumeBasic, 运行效果如下图 看了下主程序的示例代码&#xff0c;非常简单&#xff0c;可以说corestone3D这个库把很多细节都封装起来了&#xff0c;使得调用者可以很简单的快速实…

基于YOLO11深度学习的果园苹果检测与计数系统设计与实现【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

数据中心储能蓄电池状态监测管理系统 组成架构介绍

安科瑞刘鸿鹏 摘要 随着数据中心对供电可靠性要求的提高&#xff0c;蓄电池储能系统成为关键的后备电源。本文探讨了蓄电池监测系统在数据中心储能系统中的重要性&#xff0c;分析了ABAT系列蓄电池在线监测系统的功能、技术特点及其应用优势。通过蓄电池监测系统的实施&#…

Ubuntu 安装 OpenCV (C++)

版本详情&#xff1a; Ubuntu: 22.04 5.15.0-133-generic gcc: 11.4.0 g: 11.4.0 OpenCV: 4.7.0 1. 卸载 OpenCV 进入原先编译 opencv 的 build 目录&#xff0c;在该目录下打开终端&#xff0c;执行以下代码&#xff08;如果 build 已经删除了&#xff0c;可以重新编译一…

【AI工具之Deepseek+Kimi一键免费生成PPT】

1.打开Deepseek网页&#xff1a;DeepSeek 2.使用Deepseek获得一份PPT大纲&#xff08;输入背景需求约束条件进行提问&#xff09;如下图&#xff1a; 3.复制Deepseek输出的PPT大纲 4.打开Kimi网页&#xff1a;Kimi.ai - 会推理解析&#xff0c;能深度思考的AI助手 5.在Kimi中…

flutter在安卓模拟器上运行

目录 下载android studio&#xff0c;然后把其中的模拟器设为环境变量&#xff0c;然后在vscode/cursor中使用插件&#xff0c;打开安卓模拟器一、下载android studio网址mac 下载64位 ARM 二、启动android studio三、设置SDK四、打开文件 打开模拟器五、运行程序六、在vscode/…

POI pptx转图片

前言 ppt页面预览一直是个问题&#xff0c;office本身虽然有预览功能但是收费&#xff0c;一些开源的项目的预览又不太好用&#xff0c;例如开源的&#xff1a;kkfileview pptx转图片 1. 引入pom依赖 我这个项目比较老&#xff0c;使用版本较旧 <dependency><gro…

数仓搭建(hive):DWB层(基础数据层)

维度退化: 通过减少表的数量和提高数据的冗余来优化查询性能。 在维度退化中&#xff0c;相关的维度数据被合并到一个宽表中&#xff0c;减少了查询时需要进行的表连接操作。例如&#xff0c;在销售数据仓库中&#xff0c;客户信息、产品信息和时间信息等维度可能会被合并到一…

vue3 在element-plus表格使用render-header

在vue2中 element表格render-header 源码是有返回h()函数的 在vue3 element-plus 表格源码 render-header函数没有返回h函数了 所以需要用render-header方法中创建虚拟DOM节点的话需要引用h方法 <el-table-column header-align"right" align"right" …

前端带样式导出excel表格,html表格生成带样式的excel表格

众所周知&#xff0c;前端生成表格通常是用xlsx、excel.js等js库&#xff0c;但这些库想要生成时增加excel样式会很麻烦。 有这么一个js库把html表格连样式带数据一并导出为excel表格: html-table-to-excel npm install html-table-to-excel 使用 html表格&#xff1a; <…

ASP.NET JWT认证失败响应:从默认到自定义的优雅改造

本文主要介绍如何通过ASP.NET Core的JwtBearerEvents机制&#xff0c;实现JWT认证失败响应的深度定制。 1. 背景 在之前的文章《一个简单的ASP.NET一致性返回工具库》 中&#xff0c;我们介绍了 Sang.AspNetCore.CommonLibraries 这一通用库&#xff0c;它通过统一API响应模型…

AI工作流+专业知识库+系统API的全流程任务自动化

我有点悲观&#xff0c;甚至很沮丧&#xff0c;因为AI留给普通人的机会不多了&#xff0c;这既是人类之间权力的斗争&#xff0c;也是硅基生命和碳基生命的斗争。AI自动化是无法避免的趋势&#xff0c;如果人类不能平权&#xff0c;那就只能跪下接受审判。 通过整合AI工作流、专…

安卓burp抓包,bypass ssl pinning

好久好久没有发东西了。主要是懒。。。 这几天在搞apk渗透&#xff0c;遇到了burp无法抓包问题&#xff0c;觉得可以写下来。 问题描述 1. 一台安卓手机&#xff0c;装了面具&#xff0c;可以拿到root 2. 电脑上有burp&#xff0c;设置代理 3.手机和电脑连同一个网段&…

TS语言自定义脚手架

初始化 新建文件夹初始化命令 npm init -ytsc --initnpm i types/nodenpm i typescript# 处理别名npm i -D tsc-alias -y 表示选项都为yes 安装ts相关依赖 新建相关文件 bin 文件夹 src文件夹 commands 文件夹 &#xff08;命令 utils 文件夹 (封装方法&#xff09; index.t…

ETL工具: Kettle入门(示例从oracle到oracle的数据导入)

kettle介绍 ETL工具,用于对数据的抽取&#xff08;Extract), 转换(Transform),加载 (Load&#xff09; Kettle 是一种ETL工具, 现称为 Pentaho Data Integration (PDI) 特点:纯JAVA语言编写 官方学习文档 网站: https://docs.hitachivantara.com/r/en-us/pentaho-data-int…

一周学会Flask3 Python Web开发-response响应格式

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 在HTTP响应中&#xff0c;数据可以通过多种格式传输。大多数情况下&#xff0c;我们会使用HTML格式&#xff0c;这也是Flask中…

内外网隔离文件传输解决方案|系统与钉钉集成+等保合规,安全提升70%

一、背景与痛点 在内外网隔离的企业网络环境中&#xff0c;员工与外部协作伙伴&#xff08;如钉钉用户&#xff09;的文件传输面临以下挑战&#xff1a; 1. **安全性风险**&#xff1a;内外网直连可能导致病毒传播、数据泄露。 2. **操作繁琐**&#xff1a;传统方式需频繁切…

【数据结构-红黑树】

文章目录 红黑树红黑树介绍红黑树的五个基本性质红黑树的平衡原理红黑树的操作红黑树的操作 代码实现节点实现插入和查询操作 红黑树 红黑树介绍 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉查找树&#xff08;Binary Search Tree, BST&#xff09;&…