看到这个题,很明显会想到是两个“最长上升子序列”从左到右,从右到左各一遍,然后拼在一起即可。
关于最长上升子序列,普通解法是 的时间复杂度
代码如下:
class Solution {
public:
/**
* 返回最大山峰序列长度
* @param numberList int整型vector 给定的序列
* @return int整型
*/
int dp1[10005],dp2[10005];
int mountainSequence(vector<int>& numberList) {
// write code here
int max1=-1,max2=0;
int n = numberList.size();
for(int i=0;i<n;i++)
{
dp1[i]=1;
for(int j=0;j<i;j++)
{
if(numberList[j]<numberList[i]) dp1[i]=max(dp1[i],dp1[j]+1);
}
}
for(int i=n-1;i>=0;i--)
{
dp2[i]=1;
for(int j=n-1;j>i;j--)
{
if(numberList[i]>numberList[j]) dp2[i]=max(dp2[i],dp2[j]+1);
}
}
//for(int i=0;i<n;i++) printf("%d ",dp2[i]);printf("\n");
for(int i=0;i<n;i++)
{
max1=max(max1,dp1[i]+dp2[i]-1);
}
return max1;
}
};对于最长上升子序列,我们知道,有
那种二分的做法看下面代码,基本就是继承经典的那种二分求LIS,遍历每个元素的时候,记录当前维护的序列的长度,也就是以这个元素为结尾的元素的长度。然后倒着求一遍。
class Solution {
public:
/**
* 返回最大山峰序列长度
* @param numberList int整型vector 给定的序列
* @return int整型
*/
int d[1000];
int d1[1000];
int d2[1000];
int mountainSequence(vector<int>& numberList) {
// write code here
int n = numberList.size();
memset(d,0,sizeof(d));
memset(d1,0,sizeof(d1));
memset(d2,0,sizeof(d2));
int sum=0;
for (int i=0; i<n; i++)
{
if(numberList[i]>d[sum]) {
d[++sum]=numberList[i];
}
else
{
int k=lower_bound(d,d+sum,numberList[i])-d;
d[k]=numberList[i];
}
d1[i]=sum;
}
sum=0;
for (int i=n-1; i>=0; i--)
{
if(numberList[i]>d[sum]) {
d[++sum]=numberList[i];
}
else
{
int k=lower_bound(d,d+sum,numberList[i])-d;
d[k]=numberList[i];
}
d2[i]=sum;
}
int sum1=0;
for (int i=0; i<n; i++)
{
sum1=max(sum1,d1[i]+d2[i]-1);
}
return sum1;
}
};时间复杂度一下就降低了
下面这样写会更好一些
class Solution {
public:
/**
* 返回最大山峰序列长度
* @param numberList int整型vector 给定的序列
* @return int整型
*/
int mountainSequence(vector<int>& numberList) {
// write code here
int n = numberList.size(), ret = 1;
vector<int>left(n), right(n), dpl, dpr;
for (int i = 0; i < n; i++)
{
auto itl = lower_bound(dpl.begin(), dpl.end(), numberList[i]);
auto itr = lower_bound(dpr.begin(), dpr.end(), numberList[n - 1 - i]);
if (itl == dpl.end()) dpl.push_back(numberList[i]);
else *itl = numberList[i];
if (itr == dpr.end()) dpr.push_back(numberList[n - 1 - i]);
else *itr = numberList[n - 1 - i];
left[i] = dpl.size();
right[n - 1 - i] = dpr.size();
}
for (int i = 0; i < n; i++)
ret = max(ret, left[i] + right[i] - 1);
return ret;
}
};由于这个题不想卡时间,所以前一种普通做法也能过的

京公网安备 11010502036488号