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

news2025/2/22 11:55:14

矩阵最长递增路径问题

      • 题目描述
      • 数据范围:
      • 进阶要求:
      • 示例
        • 示例 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,返回0
    if (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.coloradmin.cn/o/2298230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【CLIP系列】4:目标检测(ViLD、GLIP)

目录 1 ViLD2 GLIP2.1 前言2.2 损失计算2.3 模型框架 1 ViLD OPEN-VOCABULARY OBJECT DETECTION VIA VISION AND LANGUAGE KNOWLEDGE DISTILLATION 从标题就能看出来&#xff0c;作者是把CLIP模型当成一个Teacher&#xff0c;去蒸馏他自己的网络&#xff0c;从而能Zero Shot去…

Cesium for Unity Linux版本

Cesium for Unity 直装不支持Linux 参照官方开发流程一些操作命令issues 宝藏最后运行图 参照官方开发流程 https://github.com/CesiumGS/cesium-unity/blob/main/Documentation~/developer-setup.md 系统已经安装过dotnet和cmake xuefeixuefei:~$ dotnet --version 9.0.102 …

关于 IoT DC3 中驱动(Driver)的理解

在开源IoT DC3物联网系统中&#xff0c;驱动&#xff08;Driver&#xff09;扮演着至关重要的角色&#xff0c;它充当了软件系统与物理设备之间的桥梁。驱动的主要功能是依据特定的通信协议连接到设备&#xff0c;并根据设备模板中配置的位号信息进行数据采集和指令控制。不同的…

EasyRTC嵌入式WebRTC视频通话SDK支持Web浏览器、Linux、ARM、Android、iOS

随着互联网技术的飞速发展&#xff0c;实时通信&#xff08;RTC&#xff09;已经成为现代应用中不可或缺的一部分。无论是视频会议、在线教育、远程医疗&#xff0c;还是社交娱乐&#xff0c;实时通信技术都在其中扮演着重要角色。 然而&#xff0c;WebRTC技术在PC和移动端的支…

数据库脚本MySQL8转MySQL5

由于生产服务器版本上部署的是MySQL5&#xff0c;而开发手里的脚本代码是MySQL8。所以只能降版本了… 升级版本与降级版本脚本转换逻辑一样 MySQL5与MySQL8版本SQL脚本区别 大多数无需调整、主要是字符集与排序规则 MySQL5与MySQL8版本SQL字符集与排序规则 主要操作&…

【PGCCC】commit_delay 对性能的提升:PostgreSQL 基准测试

通过禁用参数可以来调整事务工作负载synchronous_commit。该措施有惊人效果。但在操作系统崩溃期间丢失已提交事务的可能性使其成为许多应用程序无法启动的因素。因此我决定写下来。 WAL 刷新是事务数据库工作负载的瓶颈 为了确保已提交的事务不会丢失&#xff0c;PostgreSQL…

AI大模型随机初始化权重并打印网络结构方法(以Deepseekv3为例,单机可跑)

背景 当前大模型的权重加载和调用&#xff0c;主要是通过在HuggingFace官网下载并使用transformer的库来加以实现&#xff1b;其中大模型的权重文件较大&#xff08;部分>100GB&#xff09;&#xff0c;若只是快速研究网络结构和数据流变化&#xff0c;则无需下载权重。本文…

Ollama+WebUI+DeepSeek部署自己的本地大模型

前言 使用AI几乎成为互联网工作者必备技能了&#xff0c;DeepSeek的出现把AI再次推向高潮&#xff0c;在本文中&#xff0c;我们将带领大家借助 Ollama、WebUI 和 deepseek 这三个工具&#xff0c;成功搭建属于自己的本地大模型环境。Ollama 作为一款轻量级的大模型运行工具&a…

(篇六)基于PyDracula搭建一个深度学习的软件之新版本ultralytics-8.3.28调试

ultralytics-8.3.28版本debug记录 1传入文件 代码太多不粘贴在这里了&#xff0c;完整代码写在了篇三 def open_src_file(self):config_file config/fold.jsonconfig json.load(open(config_file, r, encodingutf-8))open_fold config[open_fold]if not os.path.exists(op…

NLP Word Embeddings

Word representation One-hot形式 在上一周介绍RNN类模型时&#xff0c;使用了One-hot向量来表示单词的方式。它的缺点是将每个单词视为独立的&#xff0c;算法很难学习到单词之间的关系。 比如下面的例子&#xff0c;即使语言模型已经知道orange juice是常用组合词&#xf…

使用HX搭建UNI-APP云开发项目(适合新手小白与想学云开发的宝子)

什么是uni-app云开发 uni-app云开发是uni-app提供的一套后端服务,它可以帮助开发者快速搭建起一个完整的后端服务,包括数据库、云函数、存储等。开发者只需要关注前端页面的开发,后端服务由uni-app云开发提供。 uni-app云开发的优势: 快速搭建后端服务:uni-app云开发提供了…

sql:时间盲注和boolen盲注

关于时间盲注&#xff0c;boolen盲注的后面几个获取表、列、具体数据的函数补全 时间盲注方法 import time import requests# 获取数据库名 def inject_database(url):dataname for i in range(1, 20):low 32high 128mid (low high) // 2while low < high:payload &q…

【STM32】ADC|多通道ADC采集

本次实现的是ADC实现数字信号与模拟信号的转化&#xff0c;数字信号时不连续的&#xff0c;模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法&#xff0c;使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时&#xff0c;0~ 3.3v(模拟信…

arcgis for js实现层叠立体效果

在 Web 开发中&#xff0c;利用 ArcGIS for JS 实现一些炫酷的地图效果能够极大地提升用户体验。本文将详细介绍如何使用 ArcGIS for JS 实现层叠立体效果&#xff0c;并展示最终的效果图。 效果图 实现思路 要实现层叠立体效果&#xff0c;关键在于获取边界图形的坐标&#xf…

多模态本地部署和ollama部署Llama-Vision实现视觉问答

文章目录 一、模型介绍二、预期用途1. 视觉问答(VQA)与视觉推理2. 文档视觉问答(DocVQA)3. 图像字幕4. 图像-文本检索5. 视觉接地 三、本地部署1. 下载模型2. 模型大小3. 运行代码 四、ollama部署1. 安装ollama2. 安装 Llama 3.2 Vision 模型3. 运行 Llama 3.2-Vision 五、效果…

【DeepSeek】deepseek可视化部署

目录 1 -> 前文 2 -> 部署可视化界面 1 -> 前文 【DeepSeek】DeepSeek概述 | 本地部署deepseek 通过前文可以将deepseek部署到本地使用&#xff0c;可是每次都需要winR输入cmd调出命令行进入到命令模式&#xff0c;输入命令ollama run deepseek-r1:latest。体验很…

【Git版本控制器】:第一弹——Git初识,Git安装,创建本地仓库,初始化本地仓库,配置config用户名,邮箱信息

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux网络编程 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ 相关笔记&#xff1a; https://blog.csdn.net/dj…

Fabric.js、leaferjs、pixi.js 库的对比分析

文章目录 一、引言二、参与对比的 canvas 库简介三、性能对比四、易用性对比五、功能特性对比六、综合评价与使用建议七、总结 在前端开发中&#xff0c;canvas 库为实现丰富的图形效果和交互功能提供了强大的支持。本文将对 Fabric.js、leaferjs 和 pixi.js 这三个常见的 canv…

JVM——堆的回收:引用计数发和可达性分析法、五种对象引用

目录 引用计数法和可达性分析法 引用计数法&#xff1a; 可达性分析算法&#xff1a; 五种对象引用 软引用&#xff1a; 弱引用&#xff1a; 引用计数法和可达性分析法 引用计数法&#xff1a; 引用计数法会为每个对象维护一个引用计数器&#xff0c;当对象被引用时加1&…

2.11 sqlite3数据库【数据库的相关操作指令、函数】

练习&#xff1a; 将 epoll 服务器 客户端拿来用 客户端&#xff1a;写一个界面&#xff0c;里面有注册登录 服务器&#xff1a;处理注册和登录逻辑&#xff0c;注册的话将注册的账号密码写入数据库&#xff0c;登录的话查询数据库中是否存在账号&#xff0c;并验证密码是否正确…