BM61-矩阵最长递增路径

news/2024/5/19 23:33:07/文章来源:https://blog.csdn.net/WWXDwrn/article/details/130592597

题目

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

这个路径必须满足以下条件:

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

数据范围:1≤n,m≤1000,0≤matrix[i][j]≤1000。

进阶:空间复杂度 O(nm),时间复杂度 O(nm)。

例如:当输入为[[1,2,3],[4,5,6],[7,8,9]]时,对应的输出为5,其中的一条最长递增路径如下图所示:

示例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

备注:矩阵的长和宽均不大于1000,矩阵内每个数不大于1000。


思路1:深度优先搜索(dfs)(推荐使用)

深度优先搜索一般用于树或者图的遍历,其他有分支的(如二维矩阵)也适用。

它的原理是从初始点开始,一直沿着同一个分支遍历,直到该分支结束,然后回溯到上一级继续沿着一个分支走到底,如此往复,直到所有的节点都有被访问到。

既然是查找最长的递增路径长度,那我们首先要找到这个路径的起点,起点不好直接找到,就从上到下从左到右遍历矩阵的每个元素。然后以每个元素都可以作为起点查找它能到达的最长递增路径。

如何查找以某个点为起点的最长递增路径呢?我们可以考虑深度优先搜索,因为我们查找递增路径的时候,每次选中路径一个点,然后找到与该点相邻的递增位置,相当于进入这个相邻的点,继续查找递增路径,这就是递归的子问题。因此递归过程如下:

  • 终止条件: 进入路径最后一个点后,四个方向要么是矩阵边界,要么没有递增的位置,路径不能再增长,返回上一级。
  • 返回值: 每次返回的就是本级之后的子问题中查找到的路径长度加上本级的长度。
  • 本级任务: 每次进入一级子问题,先初始化后续路径长度为0,然后遍历四个方向(可以用数组表示,下标对数组元素的加减表示去往四个方向),进入符合不是边界且在递增的邻近位置作为子问题,查找子问题中的递增路径长度。因为有四个方向,所以最多有四种递增路径情况,因此要维护当级子问题的最大值。

具体做法:

  • step 1:使用一个dp数组记录i,j处的单元格拥有的最长递增路径,这样在递归过程中如果访问到就不需要重复访问。
  • step 2:遍历矩阵每个位置,都可以作为起点,并维护一个最大的路径长度的值。
  • step 3:对于每个起点,使用dfs查找最长的递增路径:只要下一个位置比当前的位置数字大,就可以深入,同时累加路径长度。

代码1

import java.util.*;public class Solution {//记录4个方向private int[][] dirs = new int[][] {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};private int n, m;public int solve (int[][] matrix) {//边界条件判断if (matrix.length == 0 || matrix[0].length == 0) {return 0;}int res = 0;n = matrix.length;m = matrix[0].length;//j,j处的单元格拥有的最长递增路径int[][] dp = new int[m + 1][n + 1];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {//更新最大值res = Math.max(res, dfs(matrix, dp, i, j));}}return res;}//深度优先搜索,返回最大单元格数public int dfs(int[][] matrix, int[][] dp, int i, int j) {if (dp[i][j] != 0) {return dp[i][j];}dp[i][j]++;for(int k = 0; k < 4; k++) {int nexti = i + dirs[k][0];int nextj = j + dirs[k][1];//判断下一个要遍历的位置是否满足条件:在矩阵范围内且满足路径递增if(nexti >= 0 && nexti < n && nextj >= 0 && nextj < m && matrix[nexti][nextj] > matrix[i][j]) {dp[i][j] = Math.max(dp[i][j], dfs(matrix, dp, nexti, nextj) + 1);}}return dp[i][j];}
}
  • 时间复杂度:O(mn),m、n分别为矩阵的两边,遍历整个矩阵以每个点作为起点,然后递归相当于遍历填充dp矩阵。
  • 空间复杂度:O(mn),辅助矩阵的空间是一个二维数组。

思路2:广度优先搜索(bfs)

广度优先搜索与深度优先搜索不同,它是将与某个节点直接相连的其它所有节点依次访问一次之后,再往更深处,进入与其他节点直接相连的节点。

bfs的时候我们常常会借助队列的先进先出,因为从某个节点出发,我们将与它直接相连的节点都加入队列,它们优先进入,则会优先弹出,在它们弹出的时候再将与它们直接相连的节点加入,由此就可以依次按层访问。

我们可以将矩阵看成是一个有向图,一个元素到另一个元素递增,代表有向图的箭头。这样我们可以根据有向图的出度入度找到最长的路径,且这个路径在矩阵中就是递增的。

具体做法:

  • step 1:计算每个节点(单元格)所对应的出度(符合边界条件且递增),对于作为边界条件的单元格,它的值比所有的相邻单元格的值都要大,因此作为边界条件的单元格的出度都为0。利用一个二维矩阵记录每个单元格的出度
  • step 2:利用拓扑排序的思想,从所有出度为0的单元格开始进行广度优先搜索。
  • step 3:借助队列来广度优先搜索,队列中每次加入出度为0的点,即路径最远点,每次从A点到B点,便将A点出度减一。
  • step 4:每次搜索都会遍历当前层的所有单元格,更新其余单元格的出度,并将出度变为0的单元格加入下一层搜索。
  • step 5:当搜索结束时,搜索的总层数即为矩阵中的最长递增路径的长度,因为bfs的层数就是路径增长的层数。

代码

import java.util.*;public class Solution {//记录4个方向private int[][] dirs = new int[][] {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};private int n, m;public int solve (int[][] matrix) {//边界条件判断if (matrix.length == 0 || matrix[0].length == 0) {return 0;}int res = 0;n = matrix.length;m = matrix[0].length;//j,j处的单元格拥有的最长递增路径int[][] outdegrees = new int[m + 1][n + 1];for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {for (int k = 0; k < 4; k++) {int nexti = i + dirs[k][0];int nextj = j + dirs[k][1];if (nexti >= 0 && nexti < n && nextj >= 0 && nextj < m &&matrix[nexti][nextj] > matrix[i][j]) {//符合条件,记录出度outdegrees[i][j]++;}}}}//辅助队列Queue<Integer> q1 = new LinkedList<Integer>();Queue<Integer> q2 = new LinkedList<Integer>();for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (outdegrees[i][j] == 0) {//找到出度为0的入队q1.offer(i);q2.offer(j);}}}while (!q1.isEmpty()) {res++;int size = q1.size();for (int x = 0; x < size; x++) {int i = q1.poll();int j = q2.poll();//四个方向for (int k = 0; k < 4; k++) {int nexti = i + dirs[k][0];int nextj = j + dirs[k][1];//逆向搜索,所以下一步是小于if (nexti >= 0 && nexti < n && nextj >= 0 && nextj < m &&matrix[nexti][nextj] < matrix[i][j]) {//符合条件,出度递减outdegrees[nexti][nextj]--;if (outdegrees[nexti][nextj] == 0) {q1.offer(nexti);q2.offer(nextj);}}}}}return res;}
}
  • 时间复杂度:O(mn),m、n分别为矩阵的两边,相当于遍历整个矩阵两次。
  • 空间复杂度:O(mn),辅助矩阵的空间是一个二维数组。

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

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

相关文章

Cy5.5-PEG2000-Biotin,Cy5.5-聚乙二醇-生物素;Biotin-PEG-Cy5.5;可用于检测抗生物素、链霉亲和素或中性生物素

Cyanine5.5-PEG-Biotin&#xff0c;Cy5.5-聚乙二醇-生物素 中文名称;Cy5.5-聚乙二醇-生物素 英文名称;Cyanine5.5-PEG-Biotin 性状&#xff1a;粘稠液体或固体粉末&#xff0c;取决于分子量大小 溶剂&#xff1a;溶于水、氯仿、DMSO等常规性有机溶剂 分子量PEG:1k、2k、3.…

Windows11关闭Edge/Chrome浏览器触摸板双指前进后退手势(防止误触切换页面)

编辑了好久的东西&#xff0c;就因为手势误触一下子切换页面了&#xff0c;难受啊&#xff01; Mac版本的设置参考这篇&#xff08;他这个是通过终端命令做的&#xff09;&#xff1a; Mac Chrome浏览器&#xff0c;关闭双指前进、后退手势 我现在身边没有Mac&#xff0c;不知道…

VMware vSphere Replication 8.7 (for vSphere 8.0U1) - 虚拟机复制和数据保护

请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vsphere-replication-8/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 新增功能 vSphere Replication 8.7 | 2023 年 4 月 18 日 | 内部版本 21591677 vSphere Re…

【原创】免费,不限量,使用OpenAI ChatGPT方法大揭秘

文章目录 微软的Edge浏览器集成WeTab插件就可以免费使用ChatGPT1、安装最新版的Edge浏览器2、选中浏览器的配置中的扩展3、在启动新页时&#xff0c;就可以看到chatGPT了4、这就可以免费使用chatGPT啦 微软的Edge浏览器集成WeTab插件就可以免费使用ChatGPT 1、安装最新版的Edg…

Android系统原理性问题分析 - 消息传递机制的分析(Looper 和 Handler)

声明 在Android系统中经常会遇到一些系统原理性的问题&#xff0c;在此专栏中集中来讨论下。比如&#xff1a;Android为了线程安全&#xff0c;不允许在UI线程外操作UI&#xff0c;很多时候做界面刷新都需要通过Handler来通知UI组件更新。此篇参考一些博客和书籍&#xff0c;不…

【3】使用YOLOv8训练自己的目标检测数据集-【收集数据集】-【标注数据集】-【划分数据集】-【配置训练环境】-【训练模型】-【评估模型】-【导出模型】

在自定义数据上训练 YOLOv8 目标检测模型的步骤可以总结如下 6 步&#xff1a; &#x1f31f;收集数据集&#x1f31f;标注数据集&#x1f31f;划分数据集&#x1f31f;配置训练环境&#x1f31f;训练模型&#x1f31f;评估模型 1. 收集数据集 随着深度学习技术在计算机视觉领…

8 集群管理

8 集群管理 8.1 集群结构 ES通常以集群方式工作&#xff0c;这样做不仅能够提高 ES的搜索能力还可以处理大数据搜索的能力&#xff0c;同时也增加了系统的容错能力及高可用&#xff0c;ES可以实现PB级数据的搜索。 下图是ES集群结构的示意图&#xff1a; 从上图总结以下概念…

【ChirpStack 】如何获取 JWT TOKEN并利用 API 下发数据?

LoRa App Server 提供了两类 API 接口&#xff0c;其中 RESTful JSON API 提供了一个 API console&#xff0c;在AS地址的基础上使用 /api 即可访问&#xff0c;罗列了 API 端点和文档介绍&#xff0c;测试起来非常方便。 本文主要介绍 如何使用 chirpstack 的API 进行测试以及…

187页9万字企业大数据治理与云平台实施方案(word)

1 项目背景概述 1.1 项目背景理解 1.2 项目需求范围 2 项目技术方案 2.1 咨询研究服务方案 2.1.1 咨询研究服务内容 2.1.2 咨询服务方案 2.2 第三方独立评估 2.2.1 概述 2.2.2 管理办法 2.2.3 考核机制 2.3 安全咨询研究服务方案 2.3.1 安全咨询服务内…

静态库和动态库的制作与使用

1.静态库的制作与使用 小知识&#xff1a;删除命令行&#xff0c;或者是配置好的路径之类的&#xff1a;退出编辑模式后&#xff1a;dd 保存并退出&#xff1a;退出编辑模式后&#xff0c;&#xff1a;wq (1)静态库的制作 1.首先生成你需要加入的文件的.O文件。使用如下代码 …

(浙大陈越版)数据结构 第二章 线性结构 2.4 多项式的加法和乘法运算实现

目录 2.4.1多项式的加法运算实现 如何设计一个函数分别求两个一元多项式的和&#xff1f; 算法思路&#xff1a;两个指针p1&#xff0c;p2分别指向两个多项式的第一个结点&#xff08;最高项&#xff09;并循环 循环&#xff1a; 2.4.2 多项式的乘积 1.多项式的表示 2.程…

前端本地存储方案-localForage

1 前言 前端有多种本地存储方案可供选择&#xff0c;以下是其中一些常见的方案&#xff1a; Cookie&#xff1a;Cookie是一种小型的文本文件&#xff0c;可以在浏览器中存储少量数据。Cookie通常用于存储会话信息或用户偏好设置等数据&#xff08;只能存储少量数据&#xff0…

c语言实现三子棋(思路+项目展示+源代码)

&#x1f4d5;博主介绍&#xff1a;目前大一正在学习c语言&#xff0c;数据结构&#xff0c;计算机网络。 c语言学习&#xff0c;是为了更好的学习其他的编程语言&#xff0c;C语言是母体语言&#xff0c;是人机交互接近底层的桥梁。 本章来写一个三子棋小游戏吧。 让我们开启c…

eSIM证书要求-证书验证-EID

SM-DP 和 SM-DS 应该验证 EUM 和 eUICC 证书中限制的 IIN 和 EID 的一致性&#xff08;参见第 4.5.2.1.0.2 和 4.5.2.1.0.3 节&#xff09;&#xff0c;并考虑 SGP.29 [ 89]。 根据 SGP.29 [89] 颁发的 EID 没有 SGP.02 [2] 中定义的 8 位 IIN。 相反&#xff0c;它们具有可变长…

系统移植 5-10

1.进入linux内核源码目录下&#xff0c;打开Makefile文件&#xff0c;搜索vmlinux&#xff0c;找到cmd_link-vmlinux命令&#xff0c; 1179 cmd_link-vmlinux \ 1180 $(CONFIG_SHELL) $< "$(LD)" "…

NOA上车「清一色」自主品牌,哪些供应商正在突围前线

随着入门级L2进入普及周期&#xff0c;以NOA&#xff08;高速、城区&#xff09;为代表的L2/L2赛道&#xff0c;正在成为主机厂、硬件供应商、算法及软件方案商的下一波市场制高点的争夺阵地。 高工智能汽车研究院监测数据显示&#xff0c;2023年1-3月中国市场&#xff08;不含…

Linux shell编程 数组 ^ 数组排序

数组定义 数组内数据类型可以为数值也可以为字符串。 若字符串类型需要使用 " " 包含以免空格扰乱数组。 方法1 空格分隔直接定义数组 arr(10 20 30 40 50) arr1(zhangsan lisi wangwu) 方法2 指定元素下标定义&#xff0c;若跳过元素不设置会显示为空 arr([0]1…

科技云报道:ChatGPT应用爆火,安全的大数据底座何处寻?

科技云报道原创。 毫无疑问&#xff0c;AIGC正在给人类社会带来一场深刻的变革。 而剥开其令人眼花缭乱的华丽外表&#xff0c;运行的核心离不开海量的数据支持。 ChatGPT的“入侵”已经引起了各行各业对内容抄袭的担忧&#xff0c;以及网络数据安全意识的提高。 虽然AI技术…

如何考核产品经理的绩效?

公司里几乎任何一个岗位都会被考核&#xff0c;产品经理也不例外。那么在产品经理实际工作该如何去考核呢&#xff1f;相信即将步入或身在职场的产品经理一定感兴趣&#xff0c;其实产品经理考核主要分为业绩考核和文化考核两大部分&#xff0c;下面将这两部分具体聊聊。 一、…

Xilinx 7系列FPGA内置ADC

Xilinx 7系列FPGA全系内置了一个ADC&#xff0c;称之为XADC。这个XADC&#xff0c;内部是两个1mbps的ADC&#xff0c;可以采集模拟信号转为数字信号送给FPGA内部使用。 XADC内部可以直接获取芯片结温和FPGA的若干供电电压&#xff08;7系列不包括VCCO&#xff09;&#xff0c;用…