最长上升子序列
一、(n*n)算法;
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #define MAX 1000 5 using namespace std; 6 int main() 7 { 8 int n,a[MAX]={0}; 9 scanf("%d",&n); 10 for(int i=0;i<n;i++) 11 { 12 scanf("%d",&a[i]); 13 } 14 int b[MAX]={0};//记录的是以i为结尾的子序列的长度; 15 b[0]=1; 16 for(int i=1;i<n;i++) 17 { 18 b[i]=1; 19 for(int j=0;j<i;j++) 20 { 21 //如果以a[i]作结尾,枚举前面的每一个结尾,找到可以和他组成最长序列的一个,更新在b[i]里; 22 if(a[i]>a[j]&&b[j]+1>b[i]) 23 b[i]=b[j]+1; 24 } 25 } 26 int ans=0; 27 for(int i=0;i<n;i++) 28 { 29 if(ans<b[i]) 30 ans=b[i]; 31 } 32 printf("%d\n",ans); 33 34 return 0; 35 }
二、
n*lgN,的算法,最长上升子序列;
1 #include <iostream> 2 using namespace std; 3 int find(int *a,int len,int n)//修改后的二分查找,若返回值为x,则a[x]>=n 4 { 5 int left=1,right=len,mid=(left+right)/2; 6 while(left<=right) 7 { 8 if(n>a[mid]) left=mid+1; 9 else if(n<a[mid]) right=mid-1; 10 else return mid; 11 mid=(left+right)/2; 12 } 13 return left; 14 } 15 16 int main(void) 17 { 18 int n,a[100],c[100],i,j,len;//新开一变量len,用来储存每次循环结束后c中已经求出值的元素的最大下标 19 while(cin>>n) 20 { 21 for(i=0;i<n;i++) 22 cin>>a[i]; 23 c[0]=-1; 24 c[1]=a[0];//c的序列是从1开始; 25 len=1;//此时只有c[1]求出来,最长递增子序列的长度为1. 26 for(i=1;i<n;i++) 27 { 28 j=find(c,len,a[i]);//在c数组中找第一个大于等于a[i]的下标,若全小于就返回最后元素后面一个的下标; 29 c[j]=a[i];//更新该结点,全小于a[i]就把他加进去; 30 if(j>len)//要更新len,另外补充一点:由二分查找可知j只可能比len大1; 31 len=j;//更新len 32 }//c数组存的是这个序列; 33 cout<<len<<endl; 34 } 35 return 0; 36 }