329. Longest Increasing Path in a Matrix

来源:互联网 发布:法国盐之花淘宝 编辑:程序博客网 时间:2024/05/22 15:08

原题:

Discuss Pick One


Given an integer matrix, find the length of the longest increasing path.

From each cell, you can either move to four directions: left, right, up or down. You may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not allowed).

Example 1:

nums = [  [9,9,4],  [6,6,8],  [2,1,1]]

Return 4
The longest increasing path is [1, 2, 6, 9].

Example 2:

nums = [  [3,4,5],  [3,2,6],  [2,2,1]]

Return 4
The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.

Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.


思考过程:

一开始想到了暴力破解,逐个遍历,知道这个时间复杂度O(n^2),一定超时。然后想到把它们组成森林,最高的树的高度就是结果。用了一个内部类,时间复杂度是O(n)可惜最后还是TLE了:

class TreeNode{        public ArrayList<TreeNode> childrenNodes = new ArrayList<>();    }    TreeNode[][] treeNodes;    boolean[][] isNotHead;    public int longestIncreasingPathTLE(int[][] matrix) {        this.matrix = matrix;        if (matrix.length < 1) return ret;        int lenOfRow = matrix[0].length;        int lengthOfColumn = matrix.length;        treeNodes = new TreeNode[lengthOfColumn][lenOfRow];//先创建相应TreeNode节点        for (int i = 0;i < lengthOfColumn;i++)            for (int j = 0;j < lenOfRow;j++)                treeNodes[i][j] = new TreeNode();        isNotHead = new boolean[lengthOfColumn][lenOfRow];//用于存储该点是否是树根        for (int i = 0;i < lengthOfColumn;i++)//在childrenNodes里添加所有周围的比自己小的节点。            for (int j = 0;j < lenOfRow;j++){            if (i > 0) linkTreeNode(i,j,i - 1,j);            if (i < lengthOfColumn - 1) linkTreeNode(i,j,i + 1,j);            if (j > 0) linkTreeNode(i,j,i,j - 1);            if (j < lenOfRow - 1) linkTreeNode(i,j,i,j + 1);            }        for (int i = 0;i < lengthOfColumn;i++)            for (int j = 0;j < lenOfRow;j++)                if (!isNotHead[i][j])//是树根就求高度                    ret = Math.max(ret,recursiveTree(treeNodes[i][j]));        return ret;    }    public void linkTreeNode(int y,int x,int y0,int x0){        if (matrix[y][x] > matrix[y0][x0]) {            treeNodes[y][x].childrenNodes.add(treeNodes[y0][x0]);//添加关系            isNotHead[y0][x0] = true;//它是孩子节点说明不会是树根        }    }    public int recursiveTree(TreeNode treeNode){//递归计算树的高度并返回        int heightOfTree = 0;        ArrayList<TreeNode> treeNodes = treeNode.childrenNodes;        for (int i = 0;i < treeNodes.size();i++)            heightOfTree = Math.max(heightOfTree,recursiveTree(treeNodes.get(i)));        return heightOfTree + 1;    }    int ret = 0;    int[][] matrix;

后来借鉴了别人的思路:用int型二维数组存储该点向后遍历可以形成的递减链的长度。如果int[i][j] = 0,说明它没有遍历到,那就遍历它。时间复杂度是O(n).


AC代码:

int ret = 0;    int[][] matrix;    int[][] length;    int lenOfRow;    int lengthOfColumn;    public int longestIncreasingPath(int[][] matrix) {        this.matrix = matrix;        if (matrix.length < 1) return ret;        lenOfRow = matrix[0].length;        lengthOfColumn = matrix.length;        length = new int[lengthOfColumn][lenOfRow];//记录该点往下能形成多长的递减链。        for (int i = 0;i < lengthOfColumn;i++)            for (int j = 0;j < lenOfRow;j++){            if (length[i][j] == 0)                ret = Math.max(ret,recursiveCalculateHeight(i,j));            }        return ret;    }    public int recursiveCalculateHeight(int i,int j){//递归计算该点往下能形成最长的链有多长,返回最大长度并记录在length二维数组里供以后用        int ret = 0;        if (i > 0 && matrix[i][j] > matrix[i-1][j])//如果不越界而且比周围的数大,而且周围那个数没有被遍历过(length二维数组的值为0),递归            ret = Math.max(ret,length[i-1][j] == 0?(recursiveCalculateHeight(i - 1,j)):length[i-1][j]);        if (i < lengthOfColumn - 1 && matrix[i][j] > matrix[i+1][j])            ret = Math.max(ret,length[i+1][j] == 0?(recursiveCalculateHeight(i + 1,j)):length[i+1][j]);        if (j > 0 && matrix[i][j] > matrix[i][j-1])            ret = Math.max(ret,length[i][j-1] == 0?(recursiveCalculateHeight(i,j - 1)):length[i][j-1]);        if (j < lenOfRow - 1 && matrix[i][j] > matrix[i][j+1])            ret = Math.max(ret,length[i][j+1] == 0?(recursiveCalculateHeight(i,j + 1)):length[i][j+1]);        ret++;//算上这一层        length[i][j] = ret;//如果比周围数都小,就会返回1.        return ret;    }


原创粉丝点击