您的位置:首页 > 大数据 > 人工智能

算法之 数组的“距离”

2014-08-15 17:58 148 查看
Description:

给定数组A[0---n-1],找出数组中的max(j - i),其中 i< j && A[i] < A[j].这里的最大的(j-i)的值就是数组的“距离”。

方法一:直接枚举,O(n^2).

方法二:伴随数组 + 排序, O(n*logn)

此处的伴随数组的定义是: A : 3 2 1 4 那么数组A 的伴随数组即是 

A    : 3 2 1 4

index: 0 1 2 3  伴随数组即为  [(3,0),(2,1),(1,2),(4,3)]其中元素为pair。

接着,对排序之后的数组首先进行预处理,如下:

A : 4 3 2 5 1 3 2 3 == 》 A : 1 2 2 3 3 3 4 5 == 》 A : 1 2 2 3 3 3 4 5

index : 0 1 2 3 4 5 6 7 == 》 index: 4 3 6 1 5 7 0 2 == 》 index: 7 7 7 7 7 7 2 2

注意:此处必须考虑数组中的元素可能有相同的,也就是在更新j-i的值的时候必须考虑此时的A[i] 与A[j]是否相等。

方法3: O(N)
A : 4 3 5 2 1 3 2 3
lMin : 4 3 3 2 1 1 1 1 lMin[i] : A[0...i]的最小值
rMax : 5 5 5 3 3 3 3 3 rMax[i] : A[j...n-1]的最大值
代码为:

//O(N^2)
int maxIJ1(const vector<int> &A)

{

const int n = A.size();

if(n<2) return -1;

int maxdiff=0;

for(int i=0; i<n; ++i)

{

for(int j=n-1;j>i;--j)

{

//maxdiff=max(maxdiff,j-i);

if((A[j]>A[i]) && (j-i)>maxdiff)

{

maxdiff=j-i;

break;

}

}

}

return maxdiff;

}

//O(N*logN)

int maxIJ2(const vector<int> &A)

{

const int n = A.size();

if(n<2) return -1;

typedef pair<int,int> P;

vector<P> tmp(n);

for(int i=0;i<n;++i)

tmp[i]=make_pair(A[i],i);

sort(tmp.begin(), tmp.end());

//preprocessing the index

vector<int> rMaxIndex(n,0);

rMaxIndex[n-1]=tmp[n-1].second;

for(int i=n-2;i>=0;--i)

rMaxIndex[i]=max(rMaxIndex[i+1],tmp[i].second);

int maxdiff=0;

for(int i=0;i<n;++i)

{

int left=tmp[i].second;

int right=rMaxIndex[i];

assert(A[left]<=A[right]);

if(A[left]!=A[right] && (right-left)>maxdiff) //必须首先判断是否相等。用来处理数组中有相同的元素的情况

maxdiff=right-left;

}

return maxdiff;

}

//O(N)

int maxIJ(const vector<int> &A)

{

const int n = A.size();

if(n<2) return -1;

vector<int> lMin(n,0),rMax(n,0);

lMin[0]=A[0];

rMax[n-1]=A[n-1];

for(int i=1; i<n; ++i)

lMin[i] = min(lMin[i-1],A[i]);

for(int i=n-2; i>=0; --i)

rMax[i] = max(rMax[i+1],A[i]);

int maxdiff=0;

int i=0,j=0;

while(i<n && j<n)

{

if(lMin[i]<rMax[j])

{

maxdiff=max(maxdiff,j-i);

j++;

}

else

{

++i;

}

}

return maxdiff;

}
关于O(N)的算法的正确性的证明:
Obeservation: lMin与rMax都是非递增的。 

假设i*,j*是最优解,分两种情况讨论:

1  假设i先到达i*,j还没到,则此时如果i还要再移动的话,那么也就是说lMin[i]>rMax[j],又由于rMax的非递增,rMax[j]>=rMax[j*],则

lMin[i*]>rMax[j]>rMax[j*],与i*,j*是最优解矛盾。

2  假设j先到达j*,i还未到,(那么我们此时要证明的是j不会再移动了),如果j此时要移动的话,那么lMin[i]<rMax[j*],又由于i*与j*是最优解,那么就一定有lMin[i*]<rMax[j*],此时我们将i*换做i可以得到更优的解,与假设矛盾。

因此,无论ij谁先到达,都不会错过最优解,于是上述算法是正确的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数组ij AiAj max 距离
相关文章推荐