【困难】矩阵最长递增路径 (递归缓存优化)

缺乏、安全感 2022-09-14 01:53 301阅读 0赞

矩阵最长递增路径

先看题目

  1. 给定一个二维数组 matrix ,可以从任何位置出发,每一步可以向上、下、左、右四个方向移动,返回最大递增路径长度。
  2. 例子:
  3. matrix =
  4. 6 5 4
  5. 1 2 3
  6. 2 7 1
  7. 从第二行的 1 出发可形成路径 1 2 3 4 5 6 ,为最长的路径,则答案返回 6.

这道题主要考验的就是递归思路,其实还是相对容易想出来的,我们这样定义一个函数 f(i,j) 含义为获取从 i,j 位置出发所能得到的最大递增路径长度。ok 有了这层定义代码就很好出了如下。

  1. public class Question5 {
  2. public static void main(String[] args) {
  3. int[][] matrix = new int[][]{ { 6, 5, 4}, { 1, 2, 3}, { 2, 7, 1}};
  4. System.out.println(longestIncreasingPath(matrix));
  5. }
  6. public static int longestIncreasingPath(int[][] matrix) {
  7. int maxLength = 0;
  8. for (int i = 0; i < matrix.length; i++) {
  9. for (int j = 0; j < matrix[0].length; j++) {
  10. int length = process(i, j, matrix);
  11. if (maxLength < length) {
  12. maxLength = length;
  13. }
  14. }
  15. }
  16. return maxLength;
  17. }
  18. /** * 定义这样一个递归 f(i,j) 从 i,j 位置出发返回最长递增路径长度 */
  19. public static int process(int i, int j, int[][] matrix) {
  20. if (i < 0 || j < 0 || i > matrix.length || j > matrix[0].length) {
  21. return 0;
  22. }
  23. int up = 1;
  24. int down = 1;
  25. int left = 1;
  26. int right = 1;
  27. if (j - 1 >= 0 && matrix[i][j - 1] > matrix[i][j]) {
  28. up += process(i, j - 1, matrix);
  29. }
  30. if (j + 1 < matrix[0].length && matrix[i][j + 1] > matrix[i][j]) {
  31. down += process(i, j + 1, matrix);
  32. }
  33. if (i - 1 >= 0 && matrix[i - 1][j] > matrix[i][j]) {
  34. left += process(i - 1, j, matrix);
  35. }
  36. if (i + 1 < matrix.length && matrix[i + 1][j] > matrix[i][j]) {
  37. right += process(i + 1, j, matrix);
  38. }
  39. return Math.max(Math.max(up, down), Math.max(left, right));
  40. }
  41. }

在这一版中我们实现了基本的功能,但是时间复杂度上是存在问题的,最外层的双层循环的复杂度就已经达到 O(m*n) 了在乘以递归的复杂度就是很大的量级。

我们思考在递归上进行优化,不难发现我们在多次递归的过程中有很多数据是可以重复利用的,那么加个缓存就是一个很好的方案。

优化后的代码如下

  1. public class Question5 {
  2. // 增加缓存
  3. public static int[][] cache;
  4. public static void main(String[] args) {
  5. int[][] matrix = new int[][]{ { 6, 5, 4}, { 1, 2, 3}, { 2, 7, 1}};
  6. System.out.println(longestIncreasingPath(matrix));
  7. }
  8. public static int longestIncreasingPath(int[][] matrix) {
  9. int maxLength = 0;
  10. cache = new int[matrix.length][matrix[0].length];
  11. for (int i = 0; i < matrix.length; i++) {
  12. for (int j = 0; j < matrix[0].length; j++) {
  13. int length = process(i, j, matrix);
  14. if (maxLength < length) {
  15. maxLength = length;
  16. }
  17. }
  18. }
  19. return maxLength;
  20. }
  21. /** * 定义这样一个递归 f(i,j) 从 i,j 位置出发返回最长递增路径长度 */
  22. public static int process(int i, int j, int[][] matrix) {
  23. if (i < 0 || j < 0 || i > matrix.length || j > matrix[0].length) {
  24. return 0;
  25. }
  26. if (cache[i][j] != 0) {
  27. return cache[i][j];
  28. }
  29. int up = 1;
  30. int down = 1;
  31. int left = 1;
  32. int right = 1;
  33. if (j - 1 >= 0 && matrix[i][j - 1] > matrix[i][j]) {
  34. up += process(i, j - 1, matrix);
  35. }
  36. if (j + 1 < matrix[0].length && matrix[i][j + 1] > matrix[i][j]) {
  37. down += process(i, j + 1, matrix);
  38. }
  39. if (i - 1 >= 0 && matrix[i - 1][j] > matrix[i][j]) {
  40. left += process(i - 1, j, matrix);
  41. }
  42. if (i + 1 < matrix.length && matrix[i + 1][j] > matrix[i][j]) {
  43. right += process(i + 1, j, matrix);
  44. }
  45. int max = Math.max(Math.max(up, down), Math.max(left, right));
  46. cache[i][j]=max;
  47. return max;
  48. }
  49. }

加缓存的思想其实是我们日常开发中查询性能优化的常用手段了,所以说算法思想对与我们日常开发具备指导性的意义。

以上优化后时间复杂度为 O(m*n) 递归行为被缓存优化为常数基本了,在时间复杂度上以上即为最优解。

leecode 对应题目 矩阵中的最长递增路径

发表评论

表情:
评论列表 (有 0 条评论,301人围观)

还没有评论,来说两句吧...

相关阅读

    相关 329. 矩阵中的递增路径

    给定一个整数矩阵,找出最长递增路径的长度。 对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。 ![在这里插入