经典算法4之最长递增子序列

来源:互联网 发布:支付宝知托付 广告 编辑:程序博客网 时间:2024/06/15 22:25

最长递增子序列(Longest Increase Subsequence)


问题描述:

这里subsequence表明了这样的子序列不要求是连续的。比如说有子序列{1, 9, 3, 8, 11, 4, 5, 6, 4, 19, 7, 1, 7 }这样一个字符串的的最长递增子序列就是{1,3,4,5,6,7}或者{1,3,4,5,6,19}

 

方法1: 假设我们的初始的序列S1。那我们从小到大先排序一下。得到了S1'。这样我们再球 S1和S1'的最长公共子序列就可以知道答案了:

 

方法2 DP:

我们定义L(j)表示以第j个元素结尾的最长递增字串长度,是一个优化的子结构,也就是最长递增子序列.那么L(j)和L(1..j-1)的关系可以描述成

L(j) = max {L(i), i<j && Ai<Aj  } + 1;  也就是说L(j)等于之前所有的L(i)中最大的的L(i)加一.这样的L(i)需要满足的条件就是Ai<Aj.这个推断还是比较容易理解的.就是选择j之前所有的满足小于当前数组的最大值.

 

 1//最长递增子序列(Longest Increase Subsequence)
 2#include <vector>  
 3#include <iostream>
 4
 5template <typename T>
 6T max(T const & a, T const & b)
 7{
 8    return a>b?a:b;
 9}

10
11//L(j) = max {L(i), i<j && Ai<Aj  } + 1
12//return the max LIS length
13//output pos: start position of the LIS
14int lis(int n, int const data[])
15{
16    std::vector <int> L(n);
17    
18    int maxLen = 0;
19    L[0= 1;
20    for(int j=1; j<n; j++)
21    {
22        L[j]=1;
23        for(int i=0; i<j; i++)
24        {
25            if(data[i]<data[j])
26                L[j] = max(L[j], L[i]+1);
27        }

28        
29        maxLen = max(maxLen, L[j]);
30        
31        std::cout << j << " " << maxLen << std::endl;
32    }

33    
34    return maxLen;
35}

36
37
38void main()
39{
40    std::vector<int> data;
41    std::cout<<"Input data:\n";
42    int a;
43    while(std::cin>>a)
44        data.push_back(a);
45        
46    int maxN = lis(data.size(), &data[0]);
47    std::cout<<maxN;
48}

49
0 0
原创粉丝点击