今天又把最长上升子序列学了一遍,
有两种时间复杂度不同的算法来解决这个问题:
现在稍微解释一下:
(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;
}
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;
}
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;
}