code42 最长递增路径问题

166 阅读1分钟

题目描述

  • 可以从任何位置出发,每一步可以走向上、下、左、右,
  • 返回最长递增路径的长度。

举例

  • matrix =
  • [5, 4, 3]
  • [3, 1, 2]
  • [2, 1, 3]
  • 从最中心的1出发,是可以走出12345的链的,而且这是最长的递增链。
  • 所以返回长度 5

思路

  • 上下左右 四个方向都走一遍

code

public class Code42 {

    // 暴力递归
    public static int longestIncreasingPath1(int[][] matrix) {
        if (matrix == null || matrix.length <= 0) {
            return 0;
        }
        int N = matrix.length;
        int M = matrix[0].length;
        int ans = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                ans = Math.max(process1(matrix, i, j), ans);
            }
        }
        return ans;
    }

    // 暴力递归
    public static int process1(int[][] matrix, int row, int col) {
        int N = matrix.length;
        int M = matrix[0].length;
        // 上下左右 四个方向都走一遍
        int up = 0;
        int down = 0;
        int left = 0;
        int right = 0;
        // 往上走
        if (row - 1 >= 0 && matrix[row][col] < matrix[row - 1][col]) {
            up = process1(matrix, row - 1, col);
        }
        // 往下走
        if (row + 1 < N && matrix[row][col] < matrix[row + 1][col]) {
            down = process1(matrix, row + 1, col);
        }
        // 往左走
        if (col - 1 >= 0 && matrix[row][col] < matrix[row][col - 1]) {
            left = process1(matrix, row, col - 1);
        }
        // 往右走
        if (col + 1 < M && matrix[row][col] < matrix[row][col + 1]) {
            right = process1(matrix, row, col + 1);
        }
        // 当前位置 加上 四个方向的最大值
        return 1 + Math.max(Math.max(up, down), Math.max(left, right));
    }

    // 暴力递归 -> 记忆化搜索
    public static int longestIncreasingPath2(int[][] matrix) {
        if (matrix == null || matrix.length <= 0) {
            return 0;
        }
        int N = matrix.length;
        int M = matrix[0].length;
        int ans = 0;
        int[][] dp = new int[N][M];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                ans = Math.max(process2(matrix, i, j, dp), ans);
            }
        }
        return ans;
    }

    // 暴力递归 -> 记忆化搜索
    public static int process2(int[][] matrix, int row, int col, int[][] dp) {
        int N = matrix.length;
        int M = matrix[0].length;
        // 上下左右 四个方向都走一遍
        int up = 0;
        int down = 0;
        int left = 0;
        int right = 0;
        if (dp[row][col] != 0) {
            return dp[row][col];
        }
        // 往上走
        if (row - 1 >= 0 && matrix[row][col] < matrix[row - 1][col]) {
            up = process2(matrix, row - 1, col, dp);
        }
        // 往下走
        if (row + 1 < N && matrix[row][col] < matrix[row + 1][col]) {
            down = process2(matrix, row + 1, col, dp);
        }
        // 往左走
        if (col - 1 >= 0 && matrix[row][col] < matrix[row][col - 1]) {
            left = process2(matrix, row, col - 1, dp);
        }
        // 往右走
        if (col + 1 < M && matrix[row][col] < matrix[row][col + 1]) {
            right = process2(matrix, row, col + 1, dp);
        }
        // 当前位置 加上 四个方向的最大值
        dp[row][col] = 1 + Math.max(Math.max(up, down), Math.max(left, right));
        return dp[row][col];
    }


    public static void main(String[] args) {
        int[][] matrix = {
                {5, 4, 3},
                {3, 1, 2},
                {2, 1, 3}
        };
        System.out.println(longestIncreasingPath1(matrix));
        System.out.println(longestIncreasingPath2(matrix));
    }
}