1. 程式人生 > >leetcode329 Longest Increasing Path in a Matrix

leetcode329 Longest Increasing Path in a Matrix

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:

Input: nums = 
[
  [9,9,4],
  [6,6,8],
  [2
,1,1] ] Output: 4 Explanation: The longest increasing path is[1, 2, 6, 9].

Example 2:

Input: nums = 
[
  [3,4,5],
  [3,2,6],
  [2,2,1]
] 
Output: 4 
Explanation: The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.

思路就是dfs搜尋加動態儲存

但是對資料的處理及儲存方式不同會對執行速度造成很大影響。下面列出兩種方法,第一種是目前details區最快速的演算法,第二種是自己寫的。在本機的執行速度分別為10ms與50ms.

兩種方法對於資料處理的區別主要在(用fast代表快速演算法,slow同理):

fast建立包含一位數字的陣列用來儲存最終結果(用陣列是為了保證值的傳遞性),並在深度搜索的過程中隨時更新值

而slow在最後再次遍歷dp陣列找最大值;

fast在向四個方向擴充套件過程中不斷更新當前最大方向所對應的最大深度

而slow寫了一個函式取四個方向中的最大深度;

solution 1:

public int longestIncreasingPath(int[][] matrix) {
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return 0;
        } 
        int rows = matrix.length;
        int cols = matrix[0].length;
        
        
        int[] global = new int[]{1};
        int[][] dp = new int[rows][cols];
        for(int i = 0; i < rows; i++) {
            for(int j = 0; j < cols; j++) {
                dfs(matrix, i, j, dp, global);
            }
        }
        
        return global[0];
        
    }
    
    private int dfs(int[][] matrix, int row, int col, int[][] dp, int[] global) {
        if(dp[row][col] != 0) {
            return dp[row][col];
        }
        
        int rows = matrix.length;
        int cols = matrix[0].length;
        int curVal = matrix[row][col];
        int leftVal = col - 1 >= 0 ? matrix[row][col - 1] : Integer.MIN_VALUE;
        int rightVal = col + 1 < cols ? matrix[row][col + 1] : Integer.MIN_VALUE;
        int topVal = row - 1 >= 0 ? matrix[row - 1][col] : Integer.MIN_VALUE;
        int bottomVal = row + 1 < rows ? matrix[row + 1][col] : Integer.MIN_VALUE;
        
        if(curVal >= leftVal && curVal >= rightVal && curVal >= topVal && curVal >= bottomVal) {
            dp[row][col] = 1;
            return 1;
        }
        
        if(col - 1 >= 0 && curVal < leftVal) {
            dp[row][col] = dfs(matrix, row, col - 1, dp, global) + 1;
        }
        
        if(col + 1 < cols && curVal < rightVal) {
            dp[row][col] = Math.max(dp[row][col], dfs(matrix, row, col + 1, dp, global) + 1);
        }
        
        if(row - 1 >= 0 && curVal < topVal) {
            dp[row][col] = Math.max(dp[row][col], dfs(matrix, row - 1, col, dp, global) + 1);
        }
        
        if(row + 1 < rows && curVal < bottomVal) {
            dp[row][col] = Math.max(dp[row][col], dfs(matrix, row + 1, col, dp, global) + 1);
        }
        
        global[0] = Math.max(global[0], dp[row][col]);
        return dp[row][col];
    }

solution 2:

class Solution {
    public int longestIncreasingPath(int[][] matrix) {
        if(matrix==null || matrix.length==0 || matrix[0].length==0) return 0;
        int longestPath= 0, bottombound= matrix.length, rightbound= matrix[0].length;
        int[][] pathMatrix= new int[matrix.length][matrix[0].length];
        dfsPath(pathMatrix,matrix,bottombound,rightbound);
        for(int i=0; i<bottombound; i++){
            for(int j=0; j<rightbound; j++){
                longestPath= longestPath>pathMatrix[i][j]? longestPath: pathMatrix[i][j];
            }
        }
        return longestPath;
    }
    public void dfsPath(int[][] pathMatrix,int[][] matrix,int rowm,int colm){
        for(int row=0; row<rowm; row++){
            for(int col=0; col<colm; col++){
                dfsPathCore(pathMatrix,matrix,rowm,colm,row,col);
            }
        }
    }
    public int dfsPathCore(int[][] pathMatrix,int[][] matrix,int rowm,int colm,int row,int col){
        if(pathMatrix[row][col]!=0)   return pathMatrix[row][col];
        int up=0,right=0,low=0,left=0;
        if(row-1>-1){
            if(matrix[row][col]>matrix[row-1][col])
                up= dfsPathCore(pathMatrix,matrix,rowm,colm,row-1,col);
        }
        if(col+1<colm){
            if(matrix[row][col]>matrix[row][col+1])
                right= dfsPathCore(pathMatrix,matrix,rowm,colm,row,col+1);
        }
        if(row+1<rowm){
            if(matrix[row][col]>matrix[row+1][col])
                low= dfsPathCore(pathMatrix,matrix,rowm,colm,row+1,col);
        }
        if(col-1>-1){
            if(matrix[row][col]>matrix[row][col-1])
                left= dfsPathCore(pathMatrix,matrix,rowm,colm,row,col-1);
        }
        
        pathMatrix[row][col]= 1+maxInFour(up,right,low,left);
        return pathMatrix[row][col];
    }
    public int maxInFour(int u,int r,int b,int l){
        int res= u;
        if(res<r)
            res=r;
        if(res<b)
            res=b;
        if(res<l)
            res=l;
        return res;
    }
}

將slow按照fast改進:11ms

class Solution {
    public int longestIncreasingPath(int[][] matrix) {
        if(matrix==null || matrix.length==0 || matrix[0].length==0) return 0;
        int longestPath= 0, bottombound= matrix.length, rightbound= matrix[0].length;
        int[][] pathMatrix= new int[matrix.length][matrix[0].length];
        int[] global= new int[]{0};
        dfsPath(pathMatrix,matrix,bottombound,rightbound,global);
        return global[0];
    }
    public void dfsPath(int[][] pathMatrix,int[][] matrix,int rowm,int colm,int[] global){
        for(int row=0; row<rowm; row++){
            for(int col=0; col<colm; col++){
                dfsPathCore(pathMatrix,matrix,rowm,colm,row,col,global);
            }
        }
    }
    public int dfsPathCore(int[][] pathMatrix,int[][] matrix,int rowm,int colm,int row,int col,int[] global){
        if(pathMatrix[row][col]!=0)   return pathMatrix[row][col];
        int up=0,right=0,low=0,left=0,max=0;
        if(row-1>-1){
            if(matrix[row][col]>matrix[row-1][col]){
                up= dfsPathCore(pathMatrix,matrix,rowm,colm,row-1,col,global);
                max= max>=up? max:up;
            }
        }
        if(col+1<colm){
            if(matrix[row][col]>matrix[row][col+1]){
                right= dfsPathCore(pathMatrix,matrix,rowm,colm,row,col+1,global);
                max= max>=right? max:right;
            }
        }
        if(row+1<rowm){
            if(matrix[row][col]>matrix[row+1][col]){
                low= dfsPathCore(pathMatrix,matrix,rowm,colm,row+1,col,global);
                max= max>=low? max:low;
            }
                
        }
        if(col-1>-1){
            if(matrix[row][col]>matrix[row][col-1]){
                left= dfsPathCore(pathMatrix,matrix,rowm,colm,row,col-1,global);
                max= max>=left? max:left;
            }
        }
        pathMatrix[row][col]= 1+max;
        global[0]= global[0]>=pathMatrix[row][col]? global[0]:pathMatrix[row][col];
        return pathMatrix[row][col];
    }
}