【问题标题】:Most efficient way to find all combinations of n choose 2查找 n 的所有组合的最有效方法选择 2
【发布时间】:2016-11-05 14:10:21
【问题描述】:

找到n choose 22 <= n <= 100000 的所有组合的最有效方法是什么?

例如,5 choose 2

1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5

这是我迄今为止测试最坏情况的方法:

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

#define MAX_ITEMS 100000

void combinations(int[], int);

long long count = 0;

int main(void) {
    int *arr = (int*) calloc(MAX_ITEMS, sizeof(int));
    if (!arr) {
        printf("Error allocating memory.");
        exit(1);
    }

    int i, n = MAX_ITEMS;

    for (i = 0; i < MAX_ITEMS; i++) {
        arr[i] = i + 1;
    }

    clock_t start, diff;
    int msec;

    start = clock();
    combinations(arr, n);
    diff = clock() - start;

    msec = diff * 1000 / CLOCKS_PER_SEC;
    printf("\n\nTime taken %d seconds %d milliseconds", msec / 1000, msec % 1000);
    printf("\n\nPairs = %lld\n", count);

    return 0;
}

void combinations(int arr[], int n) {
    int i, j, comb1, comb2, end = n - 1;

    for (i = 0; i < end; i++) {
        for (j = i + 1; j < n; j++) {
            // simulate doing something with data at these indices
            comb1 = arr[i];
            comb2 = arr[j];
            // printf("%d %d\n", arr[i], arr[j]);
            count++;
        }
    }
}

输出

Time taken 28 seconds 799 milliseconds
Pairs = 4999950000

我可能弄错了,但时间复杂度是 O(n^2)。

是否有更有效的算法来处理最坏的情况?

【问题讨论】:

  • 你应该看看这篇文章 - stackoverflow.com/questions/127704/…
  • (n * (n-1)) / 2 怎么样?还是您在实际配对之后?如果是这样,O(n^2) 是你能做的最好的。
  • @aioobe 是的,我需要实际的配对。
  • @turion 如果您需要打印/存储所有实际对, (n*(n-1))/2 = O(n^2) 是最好的,因为它是准确的你需要的 I/O 时间,有意义吗?

标签: c algorithm performance combinatorics


【解决方案1】:

没有“最好的情况”或“最坏的情况”。您需要准确地生成 (n * (n - 1)) / 2 对,并且您当前的程序只生成这些对而不是其他任何东西。因此,您的程序是最优的(在算法分析意义上)并且是θ(n^2)

一些优化可能使用各种技巧(例如从一对到另一对的按位运算、在一次迭代中生成批量对、编译器优化等),但都不会影响算法的时间复杂度。

【讨论】:

    【解决方案2】:

    这样看,如果“n”是对的数量而不是所选数组的原始大小怎么办。您的方法的复杂性是 O(n),而不是 O(n^2)。请注意,无论您的外循环如何,您都会为内循环的每次迭代填充数组的一个索引。

    鉴于此,我认为您无法做得更好。这将是一个下限,你不能每一步生产两对!我猜这是一个最佳解决方案。

    继续——如果输出的大小是输入的 n^2,那么假设您必须触摸每个数据点一次,那么您的下限始终为 n^2。你在这里做什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-07-11
      • 1970-01-01
      • 2017-07-11
      • 2011-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多