Does there exist a Top Down Dynamic Programming solution for Longest Increasing Subsequence?

Recursive approach to solve LIS length in java would be like below -

 public int LIS(int[] arr) {
        return LISLength(arr, Integer.MIN_VALUE, 0);
    }

    public int LISLength(int[] arr, int prev, int current) {
        if (current == arr.length) {
            return 0;
        }
        int include = 0;
        if (arr[current] > prev) {
            include = 1 + LISLength(arr, arr[current], current + 1);
        }
        int exclude = LISLength(arr, prev, current + 1);
        return Math.max(include, exclude);
    }

But it would work with O(2^n) time complexity so we need to use memoization technique to reduce the complexity with below approach -

public int LIS(int[] arr) {
        int memoTable[][] = new int[arr.length + 1][arr.length];
        for (int[] l : memoTable) {
            Arrays.fill(l, -1);
        }
        return LISLength(arr, -1, 0, memoTable);
    }
    public int LISLength(int[] arr, int prev, int current, int[][] memoTable) {
        if (current == arr.length) {
            return 0;
        }
        if (memoTable[prev + 1][current] >= 0) {
            return memoTable[prev + 1][current];
        }
        int include = 0;
        if (prev < 0 || arr[current] > arr[prev]) {
            include = 1 + LISLength(arr, current, current + 1, memoTable);
        }

        int exclude = LISLength(arr, prev, current + 1, memoTable);
        memoTable[prev + 1][current] = Math.max(include, exclude);
        return memoTable[prev + 1][current];
    }

So O(n^2) would be optimized time complexity with memoization technique.


Sure. Define:

F(n) = longest increasing subsequence of sequence 1..n , and the sequence must ends with elementn

Then we get that recursion function (Top down):

F(n) = max(len(F(i)) + 1) which 0 <= i < n and array[i] < array[n]

So the answer is:

Longest increasing subsequence of F(1..n)

With memoization, we come to this code(That's Python, it's better than pseudo-code):

d = {}
array = [1, 5, 2, 3, 4, 7, 2]

def lis(n):
    if d.get(n) is not None:
        return d[n]
    length = 1
    ret = [array[n]]
    for i in range(n):
        if array[n] > array[i] and len(lis(i)) + 1 > length:
            length = len(lis(i)) + 1
            ret = lis(i) + [array[n]]
    d[n] = ret
    return ret

def get_ans():
    max_length = 0
    ans = []
    for i in range(len(array)):
        if max_length < len(lis(i)):
            ans = lis(i)
            max_length = len(lis(i))
    return ans

print get_ans() # [1, 2, 3, 4, 7]