Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 54233 | Accepted: 24254 |
Description
Your program, when given the numeric sequence, must find the length of its longest ordered subsequence.
Input
Output
Sample Input
7 1 7 3 5 9 4 8
Sample Output
4
題意:求最長上升子序列的長度;
題解:兩種算法:O( n ^ 2 ) 和 O( n * log n );
代碼如下:
(1) O( n ^ 2 )
定義dp[ i ]: 以a[ i ]爲結尾的最長上升子序列的長度。
那麼以a[ i ]爲結尾的上升子序列是以下其中之一
①只包含a[ i ]的子序列 (a[ i ]比前面的任何數都小,所以重新立一個序列)
②在滿足 j < i 並且a[ j ] < a[ i ] 的以a[ j ] 爲結尾的上升子序列末尾,再加上a[ i ]後得到的子序列
遞推關係爲: dp[ i ] = max { 1 , dp[ j ] + 1( 當 j < i 且a[ j ] < a[ i ] 時)}
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1005;
int a[maxn];
int dp[maxn];
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
int ans=0;
for(int i=0;i<n;i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(a[j]<a[i])
dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,dp[i]);
}
printf("%d\n",ans);
}
return 0;
}
(2) O( n * log n )
定義 dp[ i ]: 長度爲 i + 1 的上升子序列中末尾元素的最小值
首先將 dp 數組初始化爲 INF ,然後對 a數列中的元素逐個遍歷;對於每個a[ i ] 的值,遍歷所有 dp 直到找到一個dp[ j ]的值大於等於 a[ i ]然後用a[ i ]賦值給 dp[ j ];
最後記錄 dp數組中 不爲 INF的值的數量即可。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1005;
const int INF=0x3f3f3f3f;
int a[maxn];
int dp[maxn];
int main()
{
int n;
while(~scanf("%d",&n)){
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int i=0;i<n;i++)
dp[i]=INF;
int num=0;
for(int i=0;i<n;i++){
int pos=lower_bound(dp,dp+n,a[i])-dp;
dp[pos]=a[i];
}
for(int i=0;i<n;i++){
if(dp[i]!=INF) num++;
else break;
}
printf("%d\n",num);
}
return 0;
}