对于这个问题分别写了两种实现方法,一种为n2,一种为n*log(n),由于能力有限暂时还无法在n*log(n)时间里找出这个最短序列。
n2:一个简单的dp的问题;
n*log(n):
- 建立一个辅助数组array,依次读取数组元素 x 与数组末尾元素 top比较:
- 如果 x > top,将 x 放到数组末尾;
- 如果 x < top,则二分查找数组中第一个 大于等于x 的数,并用 x 替换它。
遍历结束之后,最长递增序列长度即为栈的大小。
注意c数组的下标代表的是子序列的长度,c数组中的值也是按递增顺序排列的。这才可能用二分查找。
推荐一个博客:http://blog.csdn.net/u013074465/article/details/45442067
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
#include<stack>
#include<map>
#include<string>
#include<set>
#include<list>
#include<functional>
#include<stdlib.h>
#define INF 0x3f3f3f3f
#define mem(a,n) memset(a,n,sizeof(n))
#define PI 3.1415926
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll inv(ll b){return b==1?1:(mod-mod/b)*inv(mod%b)%mod;}
void longest_increasing_subsequence1(){
int a[1005],n,maxx,dp[1005];
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
dp[i]=1;
}
maxx=0;
for(int i=1;i<=n;i++){
for(int j=1;j<i;j++){
if(a[i]>a[j])//不要求完全递增可改为>=
dp[i]=max(dp[i],dp[j]+1);
}
maxx=max(maxx,dp[i]);
}
printf("%d\n",maxx);
}
void longest_increasing_subsequence2(){
/*
例一:原序列为1,5,8,3,6,7
辅助数组为1,5,8,此时读到3,用3替换5,得到1,3,8; 再读6,用6替换8,得到1,3,6;再读7,得到最终栈为1,3,6,7。最长递增子序列为长度4。
例二:原序列为1,5,8,3
则最栈辅助数组为1,3,8。明显这不是最长递增子序列!
*/
int a[1005],n,maxx;
vector<int> array;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
if(array.size()==0||array.back()<a[i]){
array.push_back(a[i]);
}//
else{
int low=0,high=array.size()-1;
int mid;
while(low<high){
mid=(low+high)/2;
if(a[i]>array[mid])
low=mid+1;
else
high=mid-1;
}
array[low]=a[i];
}
}
printf("%d ",array.size());
}
int main()
{
longest_increasing_subsequence1();//n2
longest_increasing_subsequence2();//n*log(n)
return 0;
}