最长上升子序列

一、(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 }

posted on 2015-06-03 23:25  bai_yan  阅读(162)  评论(0编辑  收藏  举报

导航