码迷,mamicode.com
首页 > 其他好文 > 详细

数组的“距离”

时间:2014-08-15 19:45:19      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:数组ij aiaj   max   距离   

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谁先到达,都不会错过最优解,于是上述算法是正确的。

数组的“距离”,布布扣,bubuko.com

数组的“距离”

标签:数组ij aiaj   max   距离   

原文地址:http://blog.csdn.net/xuqingict/article/details/38475085

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!