计算所有距离的总和

时间:2015-09-09 02:32:19

标签: algorithm dynamic-programming

我已经在他们位置的一条线上获得了n分。我需要总和每对点之间的距离。是否可以处理复杂度O(n)。

示例:给定三个坐标为a(-1),b(-3),c(3)的点。 所需总额: | -1 + 3 | + | - 1 - 3 | + | -3 - 3 | = 12

请帮帮我。

4 个答案:

答案 0 :(得分:4)

  1. 计算每个序列段的长度:

    for (int i=0;i<n-1;i++) len[i]=x[i+1]-x[i];
    
  2. 请注意,这是针对排序点。如果没有,请在计算后续片段长度之前进行排序。

    1. 计算每个段在不同的成对距离中出现的次数:对于某些段,对的数量为leftSidePoints * rightSidePoints。换句话说,您计算每个段长度在总和中的贡献。

       for (int i=0;i<n-1;i++) contributionOfSegment[i]=len[i]*(i+1)*(n-i-1);
      

      i+1是左侧点,n-i-1是第i段的右侧点

    2. 答案是所有细分的贡献总和:

       int sum=0; for (i=0;i<n-1;i++) sum+=contributionOfSegment[i];
      
    3. 更新

      几乎O(N)算法,也不是O(Nlog(N))(标准排序),也不是O(maxX)(计算排序)。复杂性为O(N)loglog(maxX))或更简单O(N)*number_of_bits_in_maxX,对于32位整数,5N 几乎线性。

      正如我在上面所描述的那样,主要逻辑仍然存在。瓶颈点是排序 - O(N)*number_of_bits_in_maxX因素是排序步骤。我们将使用Van Emde Boas tree对数组进行排序。该树支持findNext(x)操作 - 在复杂O(loglogmaxX)的x之后找到下一个元素。插入也具有复杂度O(loglogmaxX)

      所以,Van Emde Boas排序看起来像:

      1. 通过O(N)*number_of_bits_in_maxXfor(i=0;i<n;i++) tree.insert(x[i])填充树,其中x是未排序的输入数组。
      2. 在未排序数组中找到O(N)分钟
      3. sortedArray [0] =分钟
      4. for(int i=1;i<n;i++) sortedArray[i] = tree.findNext(sortedArray[i-1])
      5. 然后,使用我上面的逻辑,只需将数组替换为xsortedArray

        请注意,VEBTree排序仅在理论上有意义,实际上它可能具有隐藏的常数因子,对于小Nlog(N)可能优于loglog(maxX)因此,标准排序可能是比树排序快。如果N非常大而maxX只是32或64位整数,则VEBTree会很酷。

答案 1 :(得分:0)

如果对点进行排序,我可以想到一种方法。假设我们有n分。让我们考虑两个相邻的点PiPi+1,假设Pi与其他点之间的距离为DiPi和{{1}之间的距离}是Pi+1,然后是d,那么我们可以计算从一个点到O(1)中所有其他点的距离,如果从左边的相邻点到所有其他点的距离都是已知的。我们只需要计算第一个点,并相应地更新。

等式的逻辑是,当从Di+1 = Di + i * d - (n - i - 1) * d移动到Pi时,从Pi+1到其左边所有点的所有距离都会增加Pi+1d到其右边所有点的距离减少Pi+1

答案 2 :(得分:0)

如果点按排序顺序,这是可行的。让我们举一个简单的例子,大于n = 3,因为n*(n-1)/2(所有可能的对没有重复,其中(a,b)和(b,a)被认为是重复的)在这种情况下也是3和是误导性的:

n = 4 // number of points
p = [-3, -1, 1, 3] // our points

我们将首先计算距离第一个点p[0]的所有距离,这是一个O(n)操作,因此12会产生|-3 + 1| + |-3 - 1| + |-3 - 3| = 2 + 4 + 6 = 12

我们现在观察到,由于点在一条线上并且下一个点将在第一个点的右边,所以我们可以通过简单地减去当前点和前一个点之间的距离来计算所有距离相应的点数总和:

12 - (k - 1) * dist = 12 - (4 - 1) * 2 = 12 - 6 = 6

由于点0和1之间的距离等于2,我们需要为每个先前计算的距离减去此值(前一点是k-1=3对的一部分)。在下一次迭代中,k将更小1:

6 - (k - 1) * dist = 6 - (3 - 1) * 2 = 6 - 4 = 2

所以最后的总和将是O(n),然后我们必须{n}次O(1),这会产生O(n)

这会产生一系列部分总和[12,6,2,0]=20,您不需要存储它,只是为了可视化它。

答案 3 :(得分:0)

线性顺序时间有一种可能的解决方案,无论点是排序还是未排序。那么,让我们从点n+1未分类的点开始。如上所述,这些点沿着一条线(比如说x轴),它们只有整数x值。假设第一个点是P0,最后一个是Pn。这意味着总分为n+1,总点数距离为n

  1. 遍历各点以找到最小值(minX)和最大值(maxX x 值;
  2. 创建一个位数组(称为BitArray[max - min + 1]);
  3. 再次通过积分迭代,对于您遇到的每一点,设置BitArray[minX + currentX] = true;
  4. 现在创建另一个int Distances[n]数组并开始迭代BitArray中的所有值。
    1. 第一位是真的,因为它代表点minX;
    2. 找到下一个真实位并设置Distances[0] = thisX - minX;
    3. 这样,将所有连续距离填充到Distances数组中。
  5. 到目前为止,运行时复杂度为O(maxX - minX),这是线性的。对于足够接近的点,这将是O(n)。此外,我们创建了一个数组,告诉我们索引0处的(P0,P1)之间的距离,索引1处的(P1,P2)之间,索引处的(P2,P3)之间的距离等等。

    沿x轴的点排列如下所示(虚线为x轴,每个*为点,dn为P(n-1)与Pn之间的距离),

    ---*----------*------*--------*---------....--------*---
       ^          ^      ^        ^                     ^
       P0  (d0)  P1 (d1) P2 (d2)  P3  (d3)  ....  d(n)  Pn
    

    现在,计算是O(n)。只是一个简单的总结。

    总和是:

    (1 * (n - 1) * Distances[0]) +
    (2 * (n - 2) * Distances[1]) + 
    (3 * (n - 3) * Distances[2]) +
    .
    .
    .
    (1 * (n - 1) * Distances[n-1])
    

    我如何得出该总结

    拿P0。 P0与P1到Pn的距离之和

    = d(P0, P1)  + d(P0, P2)     + ... + d(P0, Pn)
    = d[0]       + (d[0] + d[1]) + ... + (d[0] + d[1] till d[n-1])
    = (n-1)*d[0] + (n-2)*d[1]    + ... + (n-1)*d[n-1]
    

    同样地,我们采用P1并计算它从P2到Pn的距离

    然后取P3 ......直到最后只考虑P(n-1)和Pn

    之间的距离

    在总结这些距离时,我们直接得到上面提到的公式。

    因此,如果点被分类运行时间为O(n)如果点未分类正在运行时间是O(maxX - minX),它仍在线性增长。