题目描述:
给出一个长度为n的由正整数构成的序列,你需要从中删除一个正整数,很显然你有很多种删除方式,你需要对删除这个正整数以后的序列求其最长上升子串,请问在所有删除方案中,最长的上升子串长度是多少。
这里给出最长上升子串的定义:即对于序列中连续的若干个正整数,满足a[i+1]>a[i],则称这连续的若干个整数构成的子串为上升子串,在所有上升子串中,长度最长的称为最长上升子串。
输入描述:
输入第一行仅包含一个正整数n,表示给出的序列的长度。(1<=n<=100000)
接下来一行有n个正整数,即这个序列,中间用空格隔开。(1<=a_i<=100000)
输出描述:
输出仅包含一个正整数,即删除一个数字之后的最长上升子串长度。
样例输入:
5
2 1 3 2 5
样例输出:
3
对于这道题,我的思路是这样的:
在当前序列中,假如删除某个已知下标的元素,那么它的最长上升子串有两种可能:
第一种:删除这个元素后,最长上升子串仍然是没有删除这个元素前序列的最长上升子串。
第二种:删除这个元素后,最长上升子串变为删除这个元素后前后序列合并所得到的新的上升子串。
例如:如果输入1 2 3 4 1 5 6 7 8,最长上升子串就是删除5号元素后的子序列,长度为8。
如果输入9 7 8 6 5 4 3 2 1,最长上升子串就是原序列的最长上升子串,长度为2。
#include<iostream>
using namespace std;
//函数返回不删除元素时序列中的最长上升子串长度
int realLongestAscendingSubstring(int* array,int n){
int maxLength=0;
for(int i=0;i<n;i++){
int j=i;
int length=1;
for(j=i;j<n;j++){
if(array[j+1]>array[j]) length++;
else break;
}
i=j;
if(maxLength<length) maxLength=length;
}
return maxLength;
}
//模拟删除原序列的第loc个元素
int deleteVal(int* array,int n,int loc){
int length=0;//删除下标为loc元素时所得到的最长上升子串长度
//从下标为loc元素的右边开始找起,非升序时跳出,否则长度+1
int i=1;
while(loc+i!=n){
if(i==1){
if(array[loc+i]>array[loc-1]) length++;
else break;
}
else{
if(array[loc+i]>array[loc+i-1]) length++;
else break;
}
i++;
}
//从下标为loc元素的左边开始找起,非降序时跳出,否则长度+1
i=1;
while(loc-i!=-1){
if(i==1){
if(array[loc-i]<array[loc+1]) length++;
else break;
}
else{
if(array[loc-i]<array[loc-i+1]) length++;
else break;
}
i++;
}
return length;
}
//函数返回删除序列中一个元素时,从被删除元素前后扩展的最长上升子串
int longestAscendingSubstring(int* array,int n){
int maxLength=0;
//从下标0开始尝试删除数组中每个元素
for(int i=0;i<n;i++){
int length=deleteVal(array,n,i);
if(maxLength<length) maxLength=length;
}
return maxLength;
}
//函数返回删除元素时序列中的最长上升子串长度
int solve(int* array,int n){
int len1=realLongestAscendingSubstring(array,n);
int len2=longestAscendingSubstring(array,n);
//当序列为升序时,不取删除元素时序列中的最长上升子串长度
if(len1!=n) return len1>len2?len1:len2;
else return len2;
}
int main(){
int array[100000];//序列
int n;//序列长度
cin>>n;
for(int i=0;i<n;i++) cin>>array[i];
cout<<solve(array,n);
}
运行结果: