最长上升子序列

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目描述

给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少。

输入格式

第一行包含整数 N。

第二行包含 N 个整数,表示完整序列。

输出格式

输出一个整数,表示最大长度。

数据范围

1≤N≤10001≤N≤1000, −109≤数列中的数≤109

输入样例:

7
3 1 2 1 8 5 6
复制代码

输出样例:

4
复制代码

思路

通过题目我们可以很容易发现,这是一道动态规划的题目,在这里我们可以把它细分成线性DP问题。针对此类问题我们还是采用解决动态规划的一般思路,即从题目抽象出状态表示,再用具体的状态计算得出我们想要的结果。

状态表示:用f[i]数组表示一个集合:所有以第i个数结尾的上升子序列,其每个元素就具有一个属性MAX(上升子序列的最长长度)

状态计算:f[i] = max(f[j] + 1),j = 0, 1, 2, …., i – 1

代码

#include <iostream>
​
using namespace std;
​
const int N = 10010;
​
int a[N], q[N];
​
int main()
{
    int n;
    cin >> n;
    for(int i = 1;i <= n;i ++ ) cin >> a[i];
    
    
    for(int i = 1;i <= n;i ++)
    {
        q[i] = 1;// 刚开始只有自己本身一个数字
        for(int j = 1;j < i;j ++)
        {
            // 如果符合条件 ,进行更新
            if(a[j] < a[i]) q[i] = max(q[i],q[j] + 1);
        }
        
    }
    
    int ans;
    for(int i = 1;i <= n;i ++) ans =max(ans, q[i]);
    
    cout << ans << endl;
    
}
复制代码

总结

针对此类动态规划问题,我们都可以从两个层面去思考,即状态表示和状态计算。在我们明确状态所代表的含以后,可以很清楚的理清整个题目的脉络。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享