找到 n 的所有组合的最有效方法选择 2
Most efficient way to find all combinations of n choose 2
找到 n choose 2
与 2 <= 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)。
是否有更有效的算法来处理最坏的情况?
这样看,如果"n"是对数而不是选择数组的原始大小呢?您的方法的复杂性是 O(n),而不是 O(n^2)。请注意,无论您的外循环如何,您都会为内循环的每次迭代填充数组的一个索引。
鉴于此,我认为您无法做得更好。这将是一个下限,你不能每步产生两对!!我猜这是一个最佳解决方案。
继续——如果输出是输入大小的 n^2,那么你的下限总是 n^2,假设你必须接触每个数据点一次。你在这里做什么。
没有"best case"或"worst case"。您需要精确地生成 (n * (n - 1)) / 2
对,而您当前的程序只生成这些对,而没有其他任何东西。因此你的程序是最优的(在算法分析意义上)并且是 θ(n^2)
.
可以使用各种技巧进行一些优化(例如,从一对到另一对的按位运算、在一次迭代中生成批量对、编译器优化等),但 none 会影响时间复杂度算法。
找到 n choose 2
与 2 <= 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)。
是否有更有效的算法来处理最坏的情况?
这样看,如果"n"是对数而不是选择数组的原始大小呢?您的方法的复杂性是 O(n),而不是 O(n^2)。请注意,无论您的外循环如何,您都会为内循环的每次迭代填充数组的一个索引。
鉴于此,我认为您无法做得更好。这将是一个下限,你不能每步产生两对!!我猜这是一个最佳解决方案。
继续——如果输出是输入大小的 n^2,那么你的下限总是 n^2,假设你必须接触每个数据点一次。你在这里做什么。
没有"best case"或"worst case"。您需要精确地生成 (n * (n - 1)) / 2
对,而您当前的程序只生成这些对,而没有其他任何东西。因此你的程序是最优的(在算法分析意义上)并且是 θ(n^2)
.
可以使用各种技巧进行一些优化(例如,从一对到另一对的按位运算、在一次迭代中生成批量对、编译器优化等),但 none 会影响时间复杂度算法。