272. 最长公共上升子序列

时间:2020-07-11 16:50:15   收藏:0   阅读:45

技术图片

 

 解法一: f[i][j]表示数列A的前i个和数列B的前j个且以B[i]结尾的最长公共上升子序列

  f[i][j]=f[i−1][j] (a[i]≠b[j])
  f[i][j]=max(f[i−1][j],f[i−1][t]+1) (a[i]=b[j] 且 1 <= t < j)

#include <iostream>
#include <cstring>
using namespace std;

const int N = 3030;
int n;
int a[N],b[N];
int f[N][N];

int main () {
    
    scanf("%d",&n);
    for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
    for(int i = 1; i <= n; i++) scanf("%d",&b[i]);
    int res = 0;
    for(int i = 1; i <= n; i++) {
        
        for(int j = 1; j <= n; j++) {
            f[i][j] = f[i-1][j];
            
            if(a[i] == b[j]) {
                
                for(int k = j - 1; k >= 1; k--) {
                    if(b[k] < b[j]) {
                        f[i][j] = max(f[i][j],f[i][k]+1);
                    }
                }
                
            }
            res = max(res,f[i][j]);
        }
    }
    printf("%d\n",res);
    return 0;
    
}

解法二:优化时间复杂度,使用一个变量来维护遍历j之前的最大长度

#include <iostream>
#include <cstring>
using namespace std;

const int N = 3030;
int n;
int a[N],b[N];
int f[N][N];

int main () {
    
    scanf("%d",&n);
    for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
    for(int i = 1; i <= n; i++) scanf("%d",&b[i]);
    int res = 0;
    for(int i = 1; i <= n; i++) {
        int len = 0;
        for(int j = 1; j <= n; j++) {
            f[i][j] = f[i-1][j]; // 分为选i和不选i两种情况,这是不选i的情况
            
            if(a[i] == b[j]) f[i][j] = max(f[i][j],len + 1); // 更新f[i][j]
            if(a[i] > b[j]) len = max(len,f[i-1][j]); // 更新len
            res = max(res,f[i][j]);
        
        }
        
    }
    printf("%d\n",res);
    return 0;
    
}

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!