题意:
        给定一个数组,求严格上升子序列的最大长度。

方法一:
动态规划


思路:
        动态规划。
        dp[ i ]表示以a[ i ]为结尾的严格上升子序列的长度。
        针对每个a[ i ],遍历 i 前面的值a[ j ] :
            
        如果 a[ j ] < a[ i ],
          则状态转移方程:dp[ i ]=max(dp[ i ],dp[ j ]+1)。



#include <bits/stdc++.h>

using namespace std;

int n,a[205],dp[205];//dp[i]表示以a[i]为结尾的严格上升子序列的长度

int main(){
    
    while(cin >> n){
        int res=0;
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++){
            cin >> a[i];
        }
        for(int i=0;i<n;i++){//遍历每个a[i]
            dp[i]=1;//初始化为1
            for(int j=0;j<i;j++){
                if(a[j]<a[i])//确保严格上升
                    dp[i]=max(dp[i],dp[j]+1);
            }
            res=max(res,dp[i]);//维护最大值
        }
        cout << res << endl;
    }
    
    return 0;
}


时间复杂度:
空间复杂度:


方法二:
动态规划+二分

思路:
        dp[ i ]存储的长度为i+1的尽可能小的值。
        遍历每个a[ i ],
        如果严格大于dp[ ]的最后一个数,则加入dp[ ];
        否则,二分找到dp[ ]中 >= a[ i ] 的数,并用a[ i ]替换。
        最终,dp[ ]的长度即为最长严格上升子序列的长度。


    

#include <bits/stdc++.h>

using namespace std;

int n,a[205],dp[205];//dp[i]存储的长度为i+1的尽可能小的值

int main(){
    
    while(cin >> n){
        int len=0;
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++){
            cin >> a[i];
        }
        dp[len++]=a[0];//初始化
        for(int i=1;i<n;i++){//遍历每个a[i]
            if(a[i]>dp[len-1]){//如果严格大于dp[]的最后一个数,则加入dp[]
                dp[len++]=a[i];
            }else{//否则,二分找到dp[]中>=a[i]的数,并用a[i]替换
                int l=0,r=len-1,mid;
                while(l<r){
                    mid=(l+r)>>1;
                    if(dp[mid]>=a[i]){
                        r=mid;
                    }else{
                        l=mid+1;
                    }
                }
                dp[l]=a[i];//替换
            }
        }
        cout << len << endl;
    }
    
    return 0;
}



时间复杂度:
空间复杂度: