没有排名的网站怎么做,做网站时尺寸多大,网站建设公司哪个好呀net网站建设,门窗网站模板题目
给定一个 n 行 m 列矩阵 matrix #xff0c;矩阵内所有数均为非负整数。 你需要在矩阵中找到一条最长路径#xff0c;使这条路径上的元素是递增的。并输出这条最长路径的长度。
这个路径必须满足以下条件#xff1a;
对于每个单元格#xff0c;你可以往上#xff…题目
给定一个 n 行 m 列矩阵 matrix 矩阵内所有数均为非负整数。 你需要在矩阵中找到一条最长路径使这条路径上的元素是递增的。并输出这条最长路径的长度。
这个路径必须满足以下条件
对于每个单元格你可以往上下左右四个方向移动。 你不能在对角线方向上移动或移动到边界外。你不能走重复的单元格。即每个格子最多只能走一次。
数据范围1≤nm≤10000≤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数组记录ij处的单元格拥有的最长递增路径这样在递归过程中如果访问到就不需要重复访问。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];}}}}//辅助队列QueueInteger q1 new LinkedListInteger();QueueInteger q2 new LinkedListInteger();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)辅助矩阵的空间是一个二维数组。