您的位置:首页 > 其它

一个int 数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。

2012-06-07 13:40 686 查看
题目:一个int 数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。能否只用一个额外数组和少量其它空间实现。

分析:

由于是要求数组种所有符合要求的数,所以肯定要遍历数组,时间至少为O(n);

比较直观的想法是依次遍历每个元素,找出左边最大的数,看是否比该元素小,再找出右边最小的数,看是否比该元素大,这样,时间复杂度就为O(n*n),但是题目中,给出了可以用一个额外数组的提示,因此,考虑利用空间来节省时间

在网上看了些思路,有O(n)实现的,但是跟自己的思路有些区别,现将思路描述如下

原数组:a[8] = {2,1,3,5,4,7,10,9}; 辅助数组b[8]

首先定义max为a[0],然后从头至尾遍历数组a,寻找左边的都比自身小的数,当a[i] > max,将a[i]放入数组b中,并且max = a[i],单步执行如下

初始化max = a[0] = 2; i
= 1, j = 0;

a[1] = 1 < max(2) => 不操作,i++

a[2] = 3 > max(2) => b[j] = a[2], max = a[2]; j++

a[3] = 5 > max(3) => b[j] = a[3], max = a[3]; j++

。。。。。

这样一次遍历后,数组b中存放的是{3,5,7,10},即满足左边的都比自身小的元素,这里约定a[0] = 2不算,因为a[0] = 2左边没有数

按此方法,定义min = a[7],从尾至头遍历数组a,寻找右边的都比自身大的数,当a[i]
< min,将a[i]与b[j]比较,若相等,则输出,并且min = a[i],若a[i] > = min,且a[i] = b[j], 则j--,表示虽然此数满足左边都比其小,但不满足右边的要求

这里有个特殊的地方,虽然感觉好像是,找到右边都比其大的数后,在数组b中寻找该数是否存在,若存在,则该数满足要求,这样,需要遍历数组b,但其实,数组b中存放的顺序是从a的前面数往后排,因此,在从后往前遍历a时,找到符合右边要求的数,直接和数组b的最后一个数比较即可,这样时间为O(n)

说的比较抽象和乱,还是看代码清晰

代码如下:

#include <iostream>
using namespace std;
void FindMid(int *a, int len)
{
if(a == NULL && len < 2)
exit(0);
int *b = new int[len];//存放符合“左边的数都比其小”要求的数,按a中出现的次序存放
int max = a[0];	   //max为该数左边所有数中最大的
int min = a[len-1];//min为该数右边所有数中最小的
int j = 0;
for(int i=1; i < len; i++) //从前往后遍历数组a
{
if(a[i] > max)
{
b[j++] = a[i];
max = a[i];
}
}
--j; //j回退一个,这样,数组b中的元素个数是j+1个
for(int i=len-2; i >= 0; i--)//从后往前遍历,寻找“右边的数都比其大”要求的数
{
if(a[i] < min)//符合右边的要求
{
min = a[i];
if(a[i] == b[j])//若该数在数组b中,则输出,同时j--,这样下一个符合要求的数就是b[j]了
{
cout<<a[i]<<" ";
--j;
}
}
else if(a[i] == b[j])//不符合右边的要求,但是出现在数组b中,这时候也要j--,相当于把该数出栈
{
--j;
}
}
cout<<endl;
delete []b;
}
int main()
{
int a[8] = {2,1,3,5,4,7,10,9};
FindMid(a,8);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐