浅析最长上升子序列问题

来源:互联网 发布:手机淘宝账户登录不上 编辑:程序博客网 时间:2024/05/16 15:44

    DP算法解最长上升子序列问题,这里介绍两种算法O(n*n)和O(nlgn)

    以poj 2533为例。

    O(n*n):

      令a[i]为序列的第i个元素,d[i]为以元素a[i]结尾的LIS长度

      当0<j<=i-1时:

      if(a[j] >= a[i])    then d[i] = 1;

      if(a[j] < a[i])    then d[i] = max(d[i],d[j] + 1)

     

#include<cstdio>#include<iostream>#define N 1002using namespace std;int a[N],l[N];int main(void){    int n;    scanf("%d",&n);    int i,j;    for(i=1;i<=n;i++)scanf("%d",&a[i]);    int ans = 0;    for(i=1;i<=n;i++)    {l[i] = 1;for(j=1;j<=i-1;j++){    if(a[j] < a[i] && l[i] < l[j] + 1)l[i] = l[j] + 1;}ans = (l[i] > ans ? l[i] : ans);    }    cout<<ans<<endl;    return 0;}

       O(nlgn):

           令a[i]为序列的第i个元素,s[n]为最长子序列。

           开始时s[1] = a[1],若a[2] > s[1],那么 s[2] = a[2],否则 s[1] = a[2] ......

           这一步一个lower_bound()函数就解决啦

          

#include<cstdio>#include<iostream>#include<string.h>#include<stdlib.h>#include<algorithm>#define N 1002using namespace std;int a[N],s[N],d[N];int main(void){    int n;    scanf("%d",&n);    int i,j;    for(i=0;i<n;i++)scanf("%d",&a[i]);    for(i=1;i<=n;i++)s[i] = 1000000000;    int ans = 0;    for(i=0;i<n;i++)    {j = lower_bound(s+1,s+n+1,a[i]) - s;d[i] = j;s[j] = a[i];ans = max(ans,d[i]);    }    cout<<ans<<endl;    return 0;}


原创粉丝点击