zoukankan      html  css  js  c++  java
  • 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] eq-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;
        }
    
  • 相关阅读:
    【Linux】在Linux上,使用校园出校器拨号的一个脚本。
    【Android】编译CM10.1遇到的错误解决方案
    【Android】编译CM10遇到的错误解决方案
    【Android】CM在repo中使用local manifest
    一个网站的诞生 MagicDict开发总结1 [首页]
    我记录网站综合系统 1.6发布
    带有ToolTip的ListBox
    字符串的宽度
    .NET开发的文本编辑器,(又发明轮子了,VB代码,不喜误入)
    捕获输入内容
  • 原文地址:https://www.cnblogs.com/xym4869/p/13379742.html
Copyright © 2011-2022 走看看