LeetCode——矩阵中的最长递增路径

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

示例 1:
输入: nums =
[
[9,9,4],
[6,6,8],
[2,1,1]
]
输出: 4
解释: 最长递增路径为 [1, 2, 6, 9]。
示例 2:
输入: nums =
[
[3,4,5],
[3,2,6],
[2,2,1]
]
输出: 4
解释: 最长递增路径是 [3, 4, 5, 6]。注意不允许在对角线方向上移动。

A:
1.记忆化深度优先搜索:从一个单元格开始进行深度优先搜索,即可找到从该单元格开始的最长递增路径。对每个单元格分别进行深度优先搜索之后,即可得到矩阵中的最长递增路径的长度。使用记忆化深度优先搜索,当访问到一个单元格 \((i,j)\) 时,如果 \(visited[i,j]\neq-1\),说明该单元格的结果已经计算过,则直接从缓存中读取结果,如果 \(visited[i,j]=-1\),说明该单元格的结果尚未被计算过,则进行搜索,并将计算得到的结果存入缓存中。遍历完矩阵中的所有单元格之后,即可得到矩阵中的最长递增路径的长度。

    private int[] visited;
    private int[] idx = new int[]{-1, 0, 1, 0, -1};

    public int longestIncreasingPath(int[][] matrix) {
        if (matrix.length == 0)
            return 0;
        int m = matrix.length;//行数
        int n = matrix[0].length;//列数
        visited = new int[m * n];
        if (visited.length == 1)
            return 1;
        Arrays.fill(visited, -1);
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (visited[i * n + j] == -1) {
                    int result = longestPathLength(matrix, i, j);
                    max = Math.max(max, result);
                } else {
                    max = Math.max(max, visited[i * n + j]);
                }
            }
        }
        return max;
    }

    private int longestPathLength(int[][] matrix, int i, int j) {
        int m = matrix.length;//行数
        int n = matrix[0].length;//列数
        int max = 1;
        for (int k = 0; k < 4; k++) {
            int newx = i + idx[k];
            int newy = j + idx[k + 1];
            if (newx >= 0 && newy >= 0 && newx < matrix.length && newy < matrix[0].length) {
                int curr = visited[newx * n + newy];
                if(matrix[newx][newy] > matrix[i][j]){
                    if (curr == -1) {
                        max = Math.max(max, longestPathLength(matrix, newx, newy) + 1);
                    } else {
                        max = Math.max(max, curr + 1);
                    }
                }
            }
        }
        visited[i * n + j] = max;
        return max;
    }

2.拓扑排序

    private int[][] count;
    private int[] idx = new int[]{-1, 0, 1, 0, -1};

    public int longestIncreasingPath(int[][] matrix) {
        if (matrix.length == 0)
            return 0;
        int m = matrix.length;
        int n = matrix[0].length;
        count = new int[m][n];
        for (int i = 0; i < m; i++) {
            Arrays.fill(count[i], 0);
        }
        //小数指向大数
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < 4; k++) {
                    int newx = i + idx[k];
                    int newy = j + idx[k + 1];
                    if (newx >= 0 && newy >= 0 && newx < m && newy < n && matrix[newx][newy] < matrix[i][j])
                        count[i][j]++;
                }
            }
        }
        Queue<int[]> q = new LinkedList<>();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (count[i][j] == 0)
                    q.add(new int[]{i, j});
            }
        }
        int ans = 0;
        //一层一层来,直到找到最长的路径
        while (!q.isEmpty()) {
            ans++;
            int size = q.size();
            for (int i = 0; i < size; i++) {
                int[] poll = q.poll();
                int x = poll[0];
                int y = poll[1];
                for (int k = 0; k < 4; k++) {
                    int newx = x + idx[k];
                    int newy = y + idx[k + 1];
                    if (newx >= 0 && newy >= 0 && newx < m && newy < n && matrix[newx][newy] > matrix[x][y]) {
                        if (--count[newx][newy] == 0) {
                            q.add(new int[]{newx, newy});
                        }
                    }
                }
            }
        }
        return ans;
    }

猜你喜欢

转载自www.cnblogs.com/xym4869/p/13379742.html
今日推荐