算法1:
时间复杂度:O(n^2):
我们依次遍历整个序列,每一次求出从第一个数到当前这个数的最长上升子序列,直至遍历到最后一个数字为止,然后再取dp数组里最大的那个即为整个序列的最长上升子序列。我们用dp[i]来存放序列1-i的最长上升子序列的长度,那么dp[i]=max(dp[j])+1,(j∈[1, i-1]); 显然dp[1]=1,我们从i=2开始遍历后面的元素即可。
#include<iostream> #include<algorithm> #include<string.h> #include<stdio.h> using namespace std; int main() { int n,a[100]; int dp[100]; memset(dp,0,sizeof(dp)); scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",&a[i]); } dp[0]=1; for(int i=1;i<n;i++) { for(int j=0;j<n;j++) { if((a[i]>a[j])&&((dp[j]+1)>dp[i])) { dp[i]=dp[j]+1; } } } sort(dp,dp+n); printf("%d ",dp[n-1]); return 0; }
算法2:
时间复杂度:(NlogN):
除了算法一的定义之外,增加一个数组b,b[i]用以表示长度为i最长子序列的最后一个数最小可以是多少。易证:i<j时,b[i]<b[j]。
在二分查找时,一直更新b[]内容,设此时b的总长度为k,
若1. arr[i] >= b[k], 则b[k+1] = arr[i];
若2. arr[i] < b[k], 则在b[1..k]中用二分搜索大于arr[i]的最小值,返回其位置pos,然后更新b[pos]=arr[i]。