★ 问题描述:
小 D 最近很无聊 , 于是他拿来 N 个大小不一的球 , 然后他将球摆成一条直线 , 用 A1 …… An 表示球的体积大小。然后小 D 发现会有 Ai 和 Aj 之间的所有小球 Ak(i<k<j) 的体积都要比 Ai 大比 Aj 小。于是小 D 想找出这样的 Ai 和 Aj 满足以上条件并且 j-i 最大。小 D 向你求助 , 你能帮他么?输出满足条件的 i 和 j, 中间用空格隔开。
输入示例: 输出示例:
6 2 67 5 -1 -1
算法思路:
每次查找最小值和最大值,将序列分为三段:
如果最小值刚好在最大值的左边:A1,A2....,Ai,Amin,...,Amax,Ak...Aj,则递归求A1到Ai,Ak到Aj的满足条件的最大值,中间段A max-Amin肯定是最大的,不用递归。
如果最小值在最大值的右边:A1,A2....,Amax,Ai...,Ak,Amin...Aj,则递归求A1到Amax,Ai到Ak,Amin到Aj的满足条件的最大值。
代码:
#include<stdio.h> int a[100001]; //用于保存序列值 int L=0; //要求的下标相剪的最大值 int begin=0; //开始下标 int end=0; //结束下标 int n=0; //序列长度 //递归函数 void getL(int b,int e) { if(b>=0&&e<n&&(e-b)>1){//b要大于0,e要小于n,而且根据条件e和b肯定间隔要大于1 int i,l=-1; int min,max; int minIndex,maxIndex; min=10000000; max=-1; minIndex=maxIndex=0; for(i=b;i<=e;i++){//查找最小值和最大值 if(a[i]<min) { min=a[i]; minIndex=i; } if(a[i]>max) { max=a[i]; maxIndex=i; } } /*分三种情况讨论: 如果最小值刚好在最大值的左边:A1,A2....,Ai,Amin,...,Amax,Ak...Aj,则递归求A1到Ai,Ak到Aj的满足条件的最大值,中间段A max-Amin肯定是最大的,不用递归。 如果最小值在最大值的右边:A1,A2....,Amax,Ai...,Ak,Amin...Aj,则递归求A1到Amax,Ai到Ak,Amin到Aj的满足条件的最大值。 */ if((maxIndex-minIndex)>L) { L=maxIndex-minIndex; begin=minIndex; end=maxIndex; } if(maxIndex>minIndex) { if((minIndex-1)>b) getL(b,minIndex-1); if((maxIndex+1)<e) getL(maxIndex+1,e); }else{ if(maxIndex>b) getL(b,maxIndex); if((minIndex-1)>(maxIndex+1)) getL(maxIndex+1,minIndex-1); if(e>minIndex) getL(minIndex,e); } } } int main(int argc, char* argv[]) { int i; while(scanf("%d",&n)!=EOF){ L=0; begin=0; end=0; for(i=0;i<n;i++) scanf("%d",&a[i]); getL(0,n-1); if(L==0)//不存在题目要求的情况,输出"-1 -1" printf("-1 -1\n"); else printf("%d %d\n",begin+1,end+1);//题目要求的下标和我们的数组下标差1,所以要加上去 } return 0; }