数组的“距离”

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

时间: 2024-10-11 05:48:09

数组的“距离”的相关文章

每日一小练——数组的距离

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:数组的距离 内容:已知两个元素从小到大排列数组x[]和y[],请编写一个程序算出两个数组元素彼此之间差的绝度值中最小的一个 数,此值称作数组的距离. 例如:x[]有1,3,5,7,9   y[]有2,6,8  那么最短距离就是1,因为x[0]和y[0].x[1]和y[0].x[2]和y[1].x[3]和y[1]还有x[4]和 y[2]的距离都是1. 我的解法:上来没多想,打开vs2013就敲了起来,问题果然很简单,分分

指针数组,数组指针,指针函数,函数指针,二级指针详解

先看个简单的:char *p,这定义了一个指针,指针指向的数据类型是字符型,char  *(p)定义了一个指针P: char *p[4], 为指针数组,由于[]的优先级高于*,所以p先和[]结合,p[]是一个数组,暂时把p[]看成是q,也就是char *(q),定义了一个指针q,只不过q是一个数组罢了,故定义了一个数组,数组里面的数据是char *的,所以数组里面的数据为指针类型.所以char *p[4]是四个指针,这四个指针组成了一个数组,称为指针数组,既有多个指针组成的数组. char(*p

一个小的日常实践——距离阵列

上得厅堂,下得厨房,写得代码,翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:数组的距离 内容:已知两个元素从小到大排列数组x[]和y[],请编写一个程序算出两个数组元素彼此之间差的绝度值中最小的一个 数,此值称作数组的距离. 比如:x[]有1,3,5,7,9   y[]有2,6,8  那么最短距离就是1.由于x[0]和y[0].x[1]和y[0].x[2]和y[1].x[3]和y[1]还有x[4]和 y[2]的距离都是1. 我的解法:上来没多想,打开vs2013就敲了起来,问题果然非常easy

【题解】英雄数组

题目描述 英雄有两个数组A和B,两个数组的长度相同.英雄想要改变A,使得A和B距离尽量小.两个数组的距离指的是A和B有多少个对应位上的数字不相同. 英雄有一堆板子,每个板子上面有一个数字,恰好可以遮挡数组的一个位置.英雄需要把这堆板子全用完,并且数组的同一个位置最多只能放一个板子. 求最小的距离. 输入输出格式 输入格式 第一行为数据组数. 对于每组数据: 第一行为两个正整数N,M.表示数组A和B的长度以及板子的数量. 1 <= M <= N <= 50 第二行N个正整数为A数组. 第三

dijkstra 算法 找图的最短路 单源最短路

基本思路是    一个path数组存路径  一个distance数组存距离   distance[k]表示 k结点到指定的初始结点的最短路   还要个collect数组收集已经被操作过的点 先初始化distance 把目标结点的子结点的距离放进去,其他的初始化为无穷大,  每次找d中未被收集到collection中的最小值,这是最重要的,有这步才能证明最后得到的是最短路,这步是贪心思想,每次找距离最小的未在collection里的结点来,保证最后得到的最小路径,这是被证明的,这步也保证了遍历所有

Codeforces Round #136 (Div. 1)C. Little Elephant and Shifts multiset

C. Little Elephant and Shifts Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/problem/220/C Description The Little Elephant has two permutations a and b of length n, consisting of numbers from 1 to n, inclusive. Let's de

NUC_HomeWork1 -- POJ1088(DP)

D - 滑雪 Description Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激.可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你.Michael想知道载一个区域中最长底滑坡.区域由一个二维数组给出.数组的每个数字代表点的高度.下面是一个例子 1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小

图论专题小结:网络流算法之ISAP算法

ISAP算法 ISAP(Improved Shortest Augument Path)算法是改进版的SAP算法,如果对效率要求很高的时候,可以用该算法. (1)概述:算法基于这样的一个事实:每次增广之后,任意结点到汇点(在残余网络中)的最短距离都不会减小.这样,我们可以利用d[i[表示结点i到汇点的距离的下界.然后再增广过程当中不断地修改这个下界.增广的时候和Dinic算法类似,只允许沿着d[i]==d[j]+1的弧(i,j)走. 不难证明,d[i[满足两个条件:(1)d[t]=0;(2)对任

迪科斯彻算法总结

最短路之~迪科斯彻算法 迪科斯彻算法是由荷兰计算机科学家艾滋郝尔·戴克斯拉提出的.本算法使用广度优先搜索解决非负权有向图的单源最短路径问题,算法最终得到一个最短路径树.此算法常用于路由算法或者作为其他图算法一个子模块,本算法是用来找一个点到其他所有点之间的最短路径. 此算法中变量的使用: map[][]二维数组记录两点之间的权值,例如map[i][j]存放i点到j点的权值,当作为有向图时,给出i,j需要存放的只有一个map[][],但一般情况下都是用无向图,需存两个map[][],即map[i]