最长递增子序列(longest increasing subsequence) 问题详解

本文介绍了一种求解最长递增子序列的算法思路,通过动态规划的方法,逐步构建以数组中每个元素为结尾的最长递增子序列,并通过实例演示了具体的计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最长递增子序列的定义:
按照序列元素的下标号,抽取一部分元素组成子序列,子序列中的元素之间为递增的关系(下标可以不连续)。其中长度最长的递增子序列就是最长递增子序列。

方法思想:
为了求出该数组的最长递增子序列,就需要先求出在以数组中每个元素为结尾的情况下,最长的递增子序列是什么样的。因此首先要申请一块二维数组空间,存放以各个元素为结尾情况下的最长递增子序列。

首先显然可知,以0号元素为结尾的子序列只有0号元素自己。然后计算以1号元素为结尾的子序列,以此类推。

当计算n号的元素对应的子序列时,可以用n号元素与n-1号子序列的末尾元素比较,若n号元素大,则n号元素 暂时 求出的子序列就是n-1号元素对应子序列再加上n号元素。然后,将n号元素与n-2号元素对应子序列做同样对比,依次计算下去,选择一个可以使n号元素的子序列最长的情况。

按照上述方法,依次计算每个元素对应的结果之后的子序列,选择一个长度最长的序列即为整个数组的最长递增子序列。
按照同样的道理可以求出最长递减子序列。

举例说明上述思想:
对于序列A{35, 36, 39, 3, 15, 27, 6, 42}当处理到最后一个元素42时,以35, 36, 39, 3, 15, 27, 6为最末元素的最长递增序列分别为:
35
35,36
35,36,39
3
3,15
3,15,27
3,6
下面来计算42元素对应的子序列,首先将42与上述子序列末尾元素比较大小,小于42时,将42加入上述序列末尾,比较各个序列的长度,选择长度最长的,如下:
35,42
35,36,42
35,36,39,42,
3,42
3,15,42
3,15,27,42
3,6,42
这其中最长的递增序列为(35,36,39,42)和(3,15,27,42),所以序列A的最长递增子序列的长度为4,在A中长度为4的递增子序列不止一个。
则整个数组的最长递增子序列长度为4。

代码编写:

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

void lis(int a[], vector<int> *vt, int len){
    for(int i = 0; i < len; i++){
        vt[i].push_back(a[i]);
        for(int j = i - 1; j >= 0; j--){
            if(a[i] > vt[j].back() && vt[j].size() > (vt[i].size()-1)){
            //选择长度最长的 
                vt[i] = vt[j];
                vt[i].push_back(a[i]);
            }
        }           
    }
}

//求序列 35, 36, 39, 3, 15, 27, 6, 42 的最长递增子序列 
int main(){
    int len = 8;
    int a[] = {35, 36, 39, 3, 15, 27, 6, 42};

    vector<int> *vt = new vector<int>[len];
    lis(a, vt, len);

    for(int i = 0; i < len; i++){
        for(int j = 0; j < vt[i].size(); j++){
            cout<<vt[i][j]<<' ';
        }
        cout<<endl;
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值