分而治之

★ 问题描述:

小 D 最近很无聊 , 于是他拿来 N 个大小不一的球 , 然后他将球摆成一条直线 , 用 A1 …… An 表示球的体积大小。然后小 D 发现会有 Ai 和 Aj 之间的所有小球 Ak(i<k<j) 的体积都要比 Ai 大比 Aj 小。于是小 D 想找出这样的 Ai 和 Aj 满足以上条件并且 j-i 最大。小 D 向你求助 , 你能帮他么?
★ 实验任务
给出 Ai …… .Aj 的序列,要你找到满足对于 (i<k<j) 的 Ak 都大于 Ai 且小于 Aj, 并且 j-i 最大的 i,j 。 如果没找到请输出两个 -1 。
★ 数据输入
输入数据第一行包含一个整数 N 表示有 N <=100000 个球,接下来一行包含 N 个数 A1 …… An 表示每个球的体积。测试数据有多组数据,你必须处理到文件尾 (EOF)
★ 结果输出

输出满足条件的 i 和 j, 中间用空格隔开。

输入示例                                 输出示例

6                                                   2 6
8 2 7 5 6 11
2

7 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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值