zoukankan      html  css  js  c++  java
  • [LintCode] Longest Increasing Continuous subsequence II Review

    Give you an integer matrix (with row size n, column size m),find the longest increasing continuous subsequence in this matrix. (The definition of the longest increasing continuous subsequence here can start at any row or column and go up/down/right/left any direction).

    Example

    Given a matrix:

    [
      [1 ,2 ,3 ,4 ,5],
      [16,17,24,23,6],
      [15,18,25,22,7],
      [14,19,20,21,8],
      [13,12,11,10,9]
    ]
    

    return 25

    Challenge 

    O(nm) time and memory.

    Solution 1. Brute force search 

    多重循环DP遇到了困难:  从上到下循环不能解决问题, 初始状态找不到.  我们可以用暴力搜索从大往小的搜索.

    暴力搜索的解法很简单, 两层for loop 遍历每一个 A[i][j], 搜索以 A[i][j] 作为结尾元素的最长子序列. 返回所有 A.length * A[0].length 个搜索结果的最大值.

     1 public class Solution {
     2     private int[] dx = {-1, 0, 1, 0};
     3     private int[] dy = {0, 1, 0, -1};
     4     public int longestIncreasingContinuousSubsequenceII(int[][] A) {
     5         if(A == null || A.length == 0){
     6             return 0;
     7         }
     8         int max = 0;
     9         for(int i = 0; i < A.length; i++){
    10             for(int j = 0; j < A[0].length; j++){
    11                 max = Math.max(max, search(A, i, j));
    12             }
    13         }
    14         return max;
    15     }
    16     private int search(int[][] A, int x, int y){
    17         int max = 1;
    18         for(int i = 0; i < 4; i++){
    19             int nx = x + dx[i];
    20             int ny = y + dy[i];
    21             if(nx >= 0 && nx < A.length && ny >= 0 && ny < A[0].length && A[x][y] > A[nx][ny]){
    22                 max = Math.max(max, search(A, nx, ny) + 1);
    23             }
    24         }
    25         return max;
    26     }
    27 }

    Solution 2. Dynamic Programming(Search with Memoization)

    Solution 1 does a lot of redundant work computing the same subproblem over and over again. This is very inefficient. 

    To optimize this to get a better running time, we apply the time vs space tradeoff. Scarifice O(n * m) memory usage to 

    get a O(n * m) run time.

    State:

    dp[x][y]:  the length of the longest ICS that ends at A[x][y];

    computed[x][y]: whether dp[x][y] has been computed or not;

    Function: 

    dp[x][y] = dp[nx][ny] + 1 (if A[x][y] > A[nx][ny])

    Initialization: 

    dp[x][y] = 1;

    Answer: Max of dp[x][y] for x in [0.....n - 1] y in [0.....m - 1]

    Run time / Space complexity

    Space: O(n * m)

    Run time: since each position of (x, y) is only calculated once, so run time is O(n * m)

     1 public class Solution {
     2     private int[] dx = {-1, 0, 1, 0};
     3     private int[] dy = {0, 1, 0, -1};
     4     private int[][] dp;
     5     private boolean[][] computed;
     6     public int longestIncreasingContinuousSubsequenceII(int[][] A) {
     7         if(A == null || A.length == 0){
     8             return 0;
     9         }
    10         int n = A.length, m = A[0].length;
    11         dp = new int[n][m];
    12         computed = new boolean[n][m];
    13         int max = 0;
    14         for(int i = 0; i < n; i++){
    15             for(int j = 0; j < m; j++){
    16                 dp[i][j] = 1;
    17             }
    18         }
    19         for(int i = 0; i < n; i++){
    20             for(int j = 0; j < m; j++){
    21                 max = Math.max(max, search(A, i, j));    
    22             }
    23         }
    24         return max;
    25     }
    26     private int search(int[][] A, int x, int y){
    27         if(computed[x][y]){
    28             return dp[x][y];
    29         }    
    30         for(int i = 0; i < 4; i++){
    31             int nx = x + dx[i];
    32             int ny = y + dy[i];
    33             if(nx >= 0 && nx < A.length && ny >= 0 && ny < A[0].length && A[x][y] > A[nx][ny]){
    34                 dp[x][y] = Math.max(dp[x][y], search(A, nx, ny) + 1);
    35             }            
    36         }
    37         computed[x][y] = true;
    38         return dp[x][y];
    39     }
    40 }

    Follow up questions

    Q: Can you optimize the memory usage like some other dynamic programming problems?

    A: No, since to calculate dp[x][y], we need all its 4 neighbors' result, so we can't use less memory. Also, search memoization is 

    hard to optimize memory usage even if we can. This is the downside of using top down memoization search compared to 

    bottom up typical dynamic programming.

    Q: Can you reconstruct one optimal solution? 

    A: Easy. Pick one largest dp[x][y] if there are more than one. Then starting from this dp[x][y] to backtrack its neighbors of value dp[x][y] - 1, 

    do this until we find a dp[i][j] = 1.

    Related Problems

    Longest Increasing Continuous subsequence

  • 相关阅读:
    用c语言程序判断谁是小偷
    android获取Button文本 从一个按钮开关中获取文本
    android 让一个控件按钮居于底部的几种方法
    java获取文件夹下所有文件的名称
    解决 apache error 指定网络名不再可用 "an unknown filter was not added: DEFLATE"的问题
    查看window隐藏进程,用微软的ProcessExplorer查看到电脑有个“硬件中断”占用大量CPU 解决办法
    Android中Message机制的灵活应用
    Thread和Looper以及Handler和Message详解 Android开发必读
    Android的Looper类使用的5个要点
    android的消息处理机制(图+源码分析)——Looper,Handler,Message
  • 原文地址:https://www.cnblogs.com/lz87/p/6936104.html
Copyright © 2011-2022 走看看