最长递增子序列(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/难度中等)的主要内容,如果未能解决你的问题,请参考以下文章