最长递增子序列

来源:互联网 发布:方差分析用什么软件 编辑:程序博客网 时间:2024/06/04 14:29


对于这个问题分别写了两种实现方法,一种为n2,一种为n*log(n),由于能力有限暂时还无法在n*log(n)时间里找出这个最短序列。


n2:一个简单的dp的问题;


n*log(n):

  • 建立一个辅助数组array,依次读取数组元素 x 与数组末尾元素 top比较: 
    • 如果 x > top,将 x 放到数组末尾;
    • 如果 x < top,则二分查找数组中第一个 大于等于x 的数,并用 x 替换它。

遍历结束之后,最长递增序列长度即为栈的大小

注意c数组的下标代表的是子序列的长度,c数组中的值也是按递增顺序排列的。这才可能用二分查找。

数组array[i]存储的是子序列长度为i的序列最后一个值(该值是该子序列中最大的元素;如果长度为i的序列有多个,那么array[i]存放这类序列最后元素中的最小一个)。

推荐一个博客: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.1415926using 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;elsehigh=mid-1;}array[low]=a[i];}}printf("%d ",array.size());}int main(){longest_increasing_subsequence1();//n2longest_increasing_subsequence2();//n*log(n)return 0; } 


原创粉丝点击