减去排序数据

时间:2013-10-20 08:08:14

标签: algorithm data-structures

我有一个排序数组X [k]。 现在我想找到

enter image description here

我试过这个

    int ans=0;
    for(int i=1;i<=k;i++)
    {
        for(int j=i+1;j<=k;j++)
        {
            ans+=abs(X[i]-X[j]);
        }
    }

我使用上面的解决方案得到了正确的答案,但是没有优化,在某些情况下超出了时间限制。 是否有任何算法以最小的复杂性实现这一点?

4 个答案:

答案 0 :(得分:5)

我们需要计算:Sigma[i] Sigma[j>i] abs(Xi-Xj)。 (指数i,j假设在1到k之间)。

因为数组是排序的,所以对于j> i,Xj> = Xi。这允许你摆脱abs,以便你有:

Sigma[i] Sigma[j>i] (Xj - Xi)

这可以分为两个总和:

Sigma[i] Sigma[j>i] Xj  -  Sigma[i] Sigma[j>i] Xi

对于特定的jXj出现在第一笔金额中的次数是多少? X2出现一次(仅适用于i = 1且j = 2),X3出现两次(i = 1,j = 3且i = 2,j = 3)等。通常,Xj出现{{1 }},所以它为总和贡献j-1(假设基于1的索引)。

以同样的方式,(j-1)Xj在第二笔金额中显示Xi次,因此会向总数提供(k-i)

这给出了结果:(k-i)Xi。这可以简化为:

Sigma[j](j-1)Xj - Sigma[i](k-i)Xi

这是用O(n)计算的,而不是O(n ^ 2)的平凡算法。

答案 1 :(得分:1)

假设此处sorted表示

  

对于任何1≤i≤j≤N,有X i ≤X j

并将您的计算目标表示为F

  

令F(X 1..N )=Σ1≤i<1。 j≤N | X i - X j |

然后我们

  

F(X 1..N
  = F(X 2..N )+Σ1≤i≤N | X i - X 1 |
  = F(X 3..N )+Σ2≤i≤N | X i - X 2 | +Σ1≤i≤N | X i - X 1 |
  = F(X 4..N )+ ...

注意

  

Σk≤i≤N | X i - X k |
  =(N - k)×(X k + 1 - X k )+Σ k +1≤i≤N | X i - X k + 1 |

所以我们有以下迭代来计算总和:

/* 
 * assuming here the data type int is suitable for holding the result
 * N is the array length, X is the sorted array
 */
int sorted_sub_sum(int N, const int *X)
{
    int ret = 0;
    int tmp_sum = 0;
    int i;
    for (i = 0; i < N; i++)
        tmp_sum += X[i] - X[0];
    for (i = 0; i < N - 1; i++)
    {
        ret += tmp_sum;
        tmp_sum -= (N - i - 1) * (X[i + 1] - X[i]);
    }
    return ret;
}

我对这段代码做了一些简单的测试(比如数组{1,2,4,9}和{1,2,4,9,17})。如果您发现任何错误,请告诉我。

已编辑:我没有仔细阅读OP的定义,在我的回答N中表示数组长度与原始问题中的k一样。很抱歉给您带来不便。

答案 2 :(得分:0)

您可以通过O(n)时间非常简单的方式执行此操作,并且如其他答案中所述,abs函数是多余的:

int ans = 0;

for (int i = 0; i < X.lengh; i++)
    ans += ((X.length - i) * (i)) * (X[i] - X[i-1]);

这个方法基于X[i] - X[i-2] = 2(X[i] - X[i-1]) - (X[i-1] - X[i-2])的事实,这允许你打破每个计算并计算数组中两个相邻数字相减的总次数。

答案 3 :(得分:-1)

我们可以摆脱abs(阵列被排序)然后在结果中x_1出现(k-1)次为负,X_2出现1次正面而k-2次负面意味着我们完全计算它k- 3次负数和.... x_(k-1)出现k-3次正数,x_k出现k-1次正数,因此我们得到以下简化求和:

int coef = 1-k;
int sum = 0;
for(int i=0;i<k;i++)
{
    sum += coef * x[i];
    coef += 2;
}

在代码中,我认为数组是基于零的索引,x [0]等于我的描述中的x_1。