是否存在用于最长增加子序列的自顶向下动态编程解决方案?

时间:2016-06-01 07:17:59

标签: algorithm dynamic-programming pseudocode

我想知道如何使用自顶向下动态编程找到数组的LIS。 有没有这样的解决方案?你能给我一个使用自顶向下动态编程找到数组LIS的伪代码吗?我无法在互联网上找到一个。所有这些都使用Bottom Up。

3 个答案:

答案 0 :(得分:3)

在Java中以递归方式解决LIS长度的方法如下-

 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);
    }

但是它可以处理O(2 ^ n)时间复杂度,因此我们需要使用记忆技术来通过以下方法降低复杂度-

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];
    }

因此,通过记忆技术可以优化O(n ^ 2)的时间复杂度。

答案 1 :(得分:2)

不确定。定义:

F(n)=序列1..n的最长增加子序列 ,序列必须以元素 n

结束

然后我们得到递归函数(自上而下):

F(n)= max(len(F(i))+ 1)其中0 <= i <1。 n和array [i]&lt;阵列[N]

所以答案是:

F(1..n)

的最长增加子序列

使用memoization,我们来看这个代码(那是Python,它比伪代码更好):

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]

答案 2 :(得分:0)

自上而下的方法

#include <iostream>
using namespace std;
int main()
{
    int t;cin>>t;
    while(t--){
    int n; cin>>n;
    int arr[n];
    for(int i=0;i<n;i++)
        cin>>arr[i];

    int lis[n];
    for(int i=0;i<n;i++) lis[i]=1;
    lis[0]=1;
    for(int i=0;i<n;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            if(arr[i]<arr[j] && lis[i]+1>lis[j])
                lis[j] = lis[i]+1;
        }
    }


    int ans = 1;
    for(int i=0;i<n;i++)
        ans = max(ans,lis[i]);
    cout<<ans<<endl;

    }
    return  0;
}