最长递增子序列(NC91/考察次数Top32/难度中等)

Posted 码农指南

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长递增子序列(NC91/考察次数Top32/难度中等)相关的知识,希望对你有一定的参考价值。

描述:
给定数组arr,设长度为n,输出arr的最长递增子序列。(如果有多个答案,请输出其中字典序最小的)

示例1
输入:
[2,1,5,3,6,4,8,9,7]
返回值:
[1,3,4,8,9]
(题目来自牛客网)

用C++实现如下

class Solution {
public:
    /**
     * retrun the longest increasing subsequence
     * @param arr int整型vector the array
     * @return int整型vector
     */
    vector<int> LIS(vector<int>& arr) {
        //思路,使用贪心法进行求解,用vector<int>dp来存放第i个位置的前面递增的子序列,贪心表现在只保留子序列元素;
        if(arr.size()<=1)
            return arr;
        vector<int> dp;                           //定义一个dp,dp存放当前最长的子序列,dp元素的选取可体现贪心法
        vector<int> maxLength;                    //maxLength是与arr等长,记录arr当前元素处前面的最长子序列长度
        dp.push_back(arr[0]);                     //首先把首元素push进去
        maxLength.push_back(1);                   //首元素处最长子序列的长度为1
        for(int i = 1; i<arr.size(); ++i)         //遍历数组arr;
        {
            if(arr[i]>=dp.back())                 //如果新元素比较大
            {
                dp.push_back(arr[i]);             //大于,直接push进去
                maxLength.push_back(dp.size());   //因为此元素满足子序列要求,直接提取dp.size()的值存放
            }
            else                                  //如果新元素比较小
            {
                for(int j=0; j<dp.size(); ++j)    //找到第一个比新元素大的数,将其换掉
                {
                    if(dp[j]>arr[i])              //找到第一个比新元素大的数
                    {
                        dp[j]=arr[i];             //换掉
                        maxLength.push_back(j+1); //此处长度为替换掉位置值处所具有的长度,非dp.size()
                                                  //注意j和第j+1位的区别,arr[0]是第1位
                        break;                    //break跳出小的for循环,进行下一个
                    }
                }
            }
        }
        //求出了最终的dp,长度没毛病,但是内容可能不是最终解,return dp;结果不一定对,只是长度是没问题;

        //填充最长递增子序列;
        vector<int> result(dp.size());                 //dp.size()即等于返回值result实际的长度!
        for(int i=dp.size()-1; i>=0; i--)              //利用dp.size()循环对result进行求解,从后往前进行填充
        {
            for(int j=maxLength.size()-1; j>=0; j--)   //循环用于对储存每项长度的遍历,相当于arr数组
            {
                if(maxLength[j] == i+1)                //说明包含本位置的值,表示此处存储的长度值刚好等于实际长度
                {
                    result[i]=arr[j];                  //进行填充求解
                    maxLength.pop_back();              //尾部弹出,vector的尾部弹出使用pop_back()函数
                    break;                             //找到了,可以结束此次循环
                }
                maxLength.pop_back();                  //不包含本位置的值,接着找,直到找到maxLength中值等于dp实际长度的
            }
        }
        return result;
    }
};

纯手撕代码,如果觉得内容不错麻烦点个赞,后面陆续配上Top100算法题通俗易懂的讲解视频,可以花两个月时间完全掌握,进大厂不是梦,转行狗亲测!

以上是关于最长递增子序列(NC91/考察次数Top32/难度中等)的主要内容,如果未能解决你的问题,请参考以下文章

最长公共子序列-II(NC92/考察次数Top58/难度中等)

最长公共子串(NC127/考察次数Top22/难度中等)

最长回文子串(NC17/考察次数Top29/难度中等)

最长无重复子数组(NC41/考察次数Top14/难度中等)

最长公共前缀(NC55/考察次数Top64/难度简单)

最长公共前缀(NC55/考察次数Top64/难度简单)