一个序列为不无聊序列,则必须满足划分任意长度的连续子序列(包括其本身),其中至少存在一个元素仅仅出现一次,即至少有一个元素不重复
如:
12321 ——不无聊序列,任意子序列都有独特元素
123321 ——无聊序列,子序列“33”中没有独特元素
采用分治法求解,如果要成为一个不无聊序列,就必须至少有一个独特(与序列中任何数都不重复)的数,找到这个数并且进行递归
O(nlogn)
#include
#include
using namespace std;
//prepos[i]表示序列中,位于第i个元素之前,且与第i个元素相同的元素的下标是prepos[i]
//nextpos[i]表示序列中,位于第i个元素之后,且与第i个元素相同的元素的下标是nextpos[i]
int prepos[10000],nextpos[10000];
int n; //数组大小
int arr[10000]; //定义数组
map<int,int>mp; //记录每个数字出现的下标
void find(){
//赋值prepos数组
for(int i=0;i<n;i++){
int num=arr[i];
if(mp.count(num)==0){ //判断map中有没有出现该数字
prepos[i]=-1; //没出现过就赋值-1
}else{
prepos[i]=mp[num]; //出现过就赋值前一次出现时所在的索引位置
}
mp[num]=i; //更新数字对应的索引
}
mp.clear(); //清空map
//赋值nextpos数组
for(int i=n-1;i>=0;i--){
int num=arr[i];
if(mp.count(num)==0){ //判断map中有没有出现该数字
nextpos[i]=n+1; //没出现过就赋值n+1
}else{
nextpos[i]=mp[num]; //出现过就赋值前一次出现时所在的索引位置
}
mp[num]=i; //更新数字对应的索引
}
mp.clear();
}
bool judge(int left,int right){
if(left>=right) return true;
int i=left,j=right; //从序列两端开始遍历
while(i<=j){ //两端指针i,j未相遇
if(prepos[i]<left&&nextpos[i]>right){ //若序列左边存在独特(不重复)的数,则进行递归
return judge(left,i-1)&&judge(i+1,right);
}
i++;
if(prepos[j]<left&&nextpos[j]>right){ //若序列右边存在独特(不重复)的数,则进行递归
return judge(left,j-1)&&judge(j+1,right);
}
j--;
}
return false;
}
int main(){
cout<<"input seqSize: ";
cin>>n;
cout<<"input seqNum: ";
for(int i=0;i<n;i++){
cin>>arr[i];
}
cout<<"the sequence is: "<<endl;
for(int i=0;i<n;i++){
cout<<arr[i]<<"\t";
}
cout<<endl;
//找到prepos和nextpos两个数组的值
find();
//判断是否为不无聊数组
if(judge(0,n)){
cout<<"it is a non-boring sequence!";
}
else{
cout<<"it is a boring sequence!";
}
return 0;
}

