Question
from lintcode
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
Idea
In dynamic programming, state i was computed from state i - 1 as usual. BUT, when you try to compute state i from state i +1, this turns out to be a DFS search.
The trick is that the path must fit in increasing order, which makes repeated visiting impossible. It is even an easier DFS search, isn't it?
/**
* f(x, y) = 1 + [f(x + 1, y), f(x - 1, y), f(x, y - 1), f(x, y + 1)]
* .filter(increasingOrder).max()
*/
public class Solution {
/**
* @param A: An integer matrix
* @return: an integer
*/
public int longestIncreasingContinuousSubsequenceII(int[][] A) {
if (A.length == 0) return 0;
int rowLen = A.length;
int colLen = A[0].length;
int[][] cache = new int[rowLen][colLen];
int max = 0;
/**
* Since we iterate each i,j pair, path repetition may occurs
* That's why we need a cache array
*/
for(int i = 0; i < rowLen; i++)
for(int j = 0; j < colLen; j++) {
int len = searchMax(A, i, j, cache);
max = Math.max(max, len);
}
return max;
}
private int searchMax(int[][] A, int row, int col, int[][] cache) {
if(cache[row][col] != 0) return cache[row][col];
int rowLen = A.length;
int colLen = A[0].length;
int max = 0;
int[][] directions = new int[][]{{1,0},{-1,0},{0,1},{0,-1}};
for(int[] direction: directions) {
int neiborRow = row + direction[0];
int neiborCol = col + direction[1];
if (neiborRow >= 0 && neiborRow < rowLen &&
neiborCol >= 0 && neiborCol < colLen &&
// increasing order, required
A[row][col] < A[neiborRow][neiborCol]) {
int len = searchMax(A, neiborRow, neiborCol, cache);
max = Math.max(max, len);
}
}
cache[row][col] = max + 1;
return cache[row][col];
}
}