arrays - 在数组中查找与数组具有相同均值的对

标签 arrays c average complexity-theory

我正在尝试解决一个问题,我必须确定数组中与原始数组具有相同均值/平均值的对数。

虽然我已经解决了嵌套循环的问题(引用下面的代码),但我想降低解决方案的复杂性,但到目前为止我还没有任何想法。

更新:“T”只是一个代表测试用例数量的变量。您可以假设它为 1。

#include <stdio.h>
#include <stdlib.h>

int comparator(const void *p, const void *q) {
  int l = *(int *)p;
  int r = *(int *)q;
    return (l-r);
}
    
int fSum(int *Arr, int N){
    int sum = 0;

    for(int i=0; i<N; i++){
        sum+=Arr[i];
        }

    return sum;
}

int main(void) {
    int i=1, T, N, pos = 1, j=0, k=0, c = 0, sum;
    int Arr[100000];
    
    scanf("%d",&T);

    while(i<=T){
     scanf("%d", &N);
     c = 0;
     j = 0;

     while(j<N){
        scanf("%d", &Arr[j]);
        ++j;
     }

     qsort(Arr, N, sizeof(int), comparator);

     sum = fSum(Arr, N);

     for(j=0; j<N-1; j++){
        for(k=N-1; k>=j+1; k--){
           if(sum*2 == ((Arr[j]+Arr[k])*N)) {
                c++;
            }
            else{
                if(sum*2 > ((Arr[j]+Arr[k])*N))
                 break;
            }
        }
     }
       printf("%d\n", c);
     ++i;
    }
    return 0;
}

最佳答案

解决此类问题的一般方法是维护两个索引的单个循环。一个索引从数组的开头开始,另一个在结尾。当索引在中间相遇时,循环结束。在循环体中,代码必须决定是更新一个索引、另一个索引,还是同时更新两个索引。

对于这个特殊问题,还有一些额外的皱纹,这是由数组中的重复项引起的。

例如,给定数组 { 1, 1, 1, 4, 5, 12, 15, 15, 18 },有 7 对。三个 1 可以与两个 15 中的任何一个匹配,给出 6 种可能的对。 4,12 对是第七对。因此,当代码找到一对具有正确平均值的不同数字时,它必须计算每个数字的重复次数。然后,对的数量由两个计数的乘积更新。

给定数组 { 2, 3, 4, 8, 8, 8, 12, 12, 15 },有 5 对。由于三个 8 而形成三对,加上将 4 与 12 配对的两种方法。当平均值出现在数组中并重复时,一个索引将到达平均值的第一个实例,而另一个将到达最后一个实例.从这两个指标可以计算出重复计数,对数就是选择任意两个重复项的方法数。

这是一个使用单个循环更新两个索引的示例实现:

#include <stdio.h>

void showArray(int Arr[], int N)
{
    printf("Arr[] = {");
    if (N > 0)
        printf(" %d", Arr[0]);
    for (int i = 1; i < N; i++)
        printf(", %d", Arr[i]);
    printf(" }\n");
}

int computeSum(int Arr[], int N)
{
    int sum = 0;
    for (int i=0; i < N; i++)
        sum += Arr[i];
    return sum;
}

int solve(int Arr[], int N)
{
    showArray(Arr, N);
    int sum = computeSum(Arr, N);
    printf("N=%d sum=%d\n", N, sum);

    int pairs = 0;
    for (int j=0, k=N-1; k > j; )
    {
        if ((Arr[j] + Arr[k])*N > sum*2)
        {
            // the average is too high, so skip the larger value
            k--;
        }
        else if ((Arr[j] + Arr[k])*N < sum*2)
        {
            // the average is too low, so skip the smaller value
            j++;
        }
        else if (Arr[j] == Arr[k])
        {
            // handle the case where the average value is present and duplicated
            int repeat = k - j + 1;
            pairs += (repeat * (repeat-1)) / 2;
            break;
        }
        else
        {
            // handle the case where two distinct numbers in the array have the correct average
            // note that if there are duplicates of the numbers, the indexes are updated to the next non-duplicate
            int oldj = j++;
            while (Arr[j] == Arr[oldj])
                j++;
            int oldk = k--;
            while (Arr[k] == Arr[oldk])
                k--;
            pairs += (j - oldj) * (oldk - k);
        }
    }

    return pairs;
}

#define len(arr) (sizeof(arr) / sizeof(arr[0]))

int main(void)
{
    int Arr1[] = { 1, 4, 5, 6, 6, 7, 7, 11, 15, 18 };
    printf("pairs=%d\n\n", solve(Arr1, len(Arr1)));

    int Arr2[] = { 1, 1, 1, 4, 5, 12, 15, 15, 18 };
    printf("pairs=%d\n\n", solve(Arr2, len(Arr2)));

    int Arr3[] = { 2, 3, 4, 8, 8, 8, 12, 12, 15 };
    printf("pairs=%d\n\n", solve(Arr3, len(Arr3)));
}

代码输出:

Arr[] = { 1, 4, 5, 6, 6, 7, 7, 11, 15, 18 }
N=10 sum=80
pairs=2

Arr[] = { 1, 1, 1, 4, 5, 12, 15, 15, 18 }
N=9 sum=72
pairs=7

Arr[] = { 2, 3, 4, 8, 8, 8, 12, 12, 15 }
N=9 sum=72
pairs=5

关于arrays - 在数组中查找与数组具有相同均值的对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71976182/

相关文章:

php - 如何 SQL 查询特定 JSON 格式的父子关系?

c++ - 我如何使用带有类的数组

python - 元组索引 numpy 数组的奇怪行为

c - 整数上溢/下溢

c - BST 中的段错误

android - 使用数组元素的索引播放基于数组元素的声音

java - 如何在不中断java程序其余部分的情况下中断while循环?

python - 平均功能不是平均而是重置

c++ - 基于另一个 vector c++中相似性的 vector 的条件平均

使用 make 编译成 32 位