最长上升子序列

来源:互联网 发布:知客文化传播 培训 编辑:程序博客网 时间:2024/06/06 00:30

今天又把最长上升子序列学了一遍,

有两种时间复杂度不同的算法来解决这个问题:

现在稍微解释一下:
(1)O(n^n)
   给你一个序列:1  3 2 4 8 7  a[i=1...i=6]
   我们用dp[i]表示 从第1个数开始到第i个数结束的最长上升子序列的长度。经典dp;
  #include <iostream>
using namespace std;
int a[110];
int dp[110];
int main()
{
  int t;
  int n;
  cin>>t;
  while(t--)
  {
    cin>>n;
    memset(dp,1,sizeof(dp));
    for(int i=1;i<=n;i++)  
      cin>>a[i];
    for(int i=2;i<=n;i++)
    {
      for(int j=1;j<i;j++)
            if(a[j]<a[i])
              dp[i]=max(dp[i],dp[j]+1);
    }
   int maxn=-999;
   for(int i=1;i<=n;i++)
   {
       if(dp[i]>maxn)maxn=dp[i];
   }
    cout<<maxn<<endl;
  }
  return 0;  
}
(2)O(n*logn)
   从第一种方法中,我们已经知道了dp[i]表示的是到第i个数结束的最长上升子序列的长度。那么假设现在有 :dp[x]==dp[y]&&a[x]<a[y]   那最优选法是将a[x]进入序列还是让a[y]
进入序列呢??? 显然让a[x]进入序列是最优的,因为a[x]<a[y],那么a[x]相对于a[y]更有潜力,因为时间关系,先附上代码:
#include <iostream>
using namespace std;
int a[110],d[110],
int BinSearch(int key,int *d,int low,int high)
{
    while(low<=hign)
    {
       int mid=low+(high-low)/2;
       if(d[mid]<key&&key<=d[mid+1])
            return mid;
       else if(d[mid]<key)
              low=mid+1;
       else
              high=mid-1;
    }
}
int lis(int *a,int n,int *d)
{
  int i,j,len;
  d[1]=a[1];
  len=1;
  for(i=2;i<=n;i++)
    {
     if(d[i-1]<a[i])
        j=++len;
     else
        j=BinSearch(a[i],d,1,len);
     d[j]=a[i];
    }
  return len;
}
int main()
{
  int t;
  int n;
  cin>>t;
  while(t--)
  {
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    cout<<lis(a,n,d)<<endl;
  }
  
  return 0;  
}

 

0 0
原创粉丝点击