【发布时间】:2013-12-26 16:53:09
【问题描述】:
我有一个包含整数(不一定不同)的方阵。我需要最快的方法来找到其中不同元素的数量。我试图将整数存储在一维数组中,对其进行排序,然后找到不同元素的数量......但显然,它不够快。您能推荐一个更好更快的 C 语言程序吗?
【问题讨论】:
-
值的约束是什么?价值观是积极的吗?有上限吗?
我有一个包含整数(不一定不同)的方阵。我需要最快的方法来找到其中不同元素的数量。我试图将整数存储在一维数组中,对其进行排序,然后找到不同元素的数量......但显然,它不够快。您能推荐一个更好更快的 C 语言程序吗?
【问题讨论】:
最快的速度很大程度上取决于您正在处理的数据、所涉及结构的大小等。
你对整数可以取的值有限制吗?如果是这样,那么保持一个由整数值索引的数组,初始化为零,以跟踪该值在矩阵中有多少个副本,这可能是最快且空间使用合理的。
如果没有,那么可能使用哈希表来做类似的事情会最快。
但无论如何,为问题提供更精确的参数会非常有帮助。
【讨论】:
整数值 0-99 的有界集合
矩阵大小 300 x 300
int array[100];
int i;
int j;
int n_unique = 0;
for (i=0;i<300;i++) {
if (n_unique == 100) break;
for (j=0;j<300;j++) {
if (array[mat[i][j]] == 0) {
array[mat[i][j]] = 1;
n_unique++;
if (n_unique == 100) break;
}
}
}
算法是 O(n)
【讨论】:
对于任何算法,通常都会在速度、内存和复杂性之间进行折衷。正如其他人所说,您对数据的了解越多,您制定算法的速度就越快。假设您有 1 到 100 之间的数字(例如),您将能够使用这些信息真正优化算法。
我花时间编写了适用于任何数据集的示例算法。这假设您的集合大小足够小或者您有足够的可用内存。基本上,简短的版本是分配一个与原始二维数组一样多的元素的数组。然后循环原始数组并将唯一元素放入新数组的框中。最后统计一下新数组的元素个数:
#include <stdio.h> /* printf, scanf, puts, NULL */
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
typedef int bool;
#define TRUE 1
#define FALSE 0
/* The actual algorithm function - finds the number of unique values */
int NumberUniqueValues(int **array, int width, int height)
{
int i = 0, j = 0, k = 0, maxFilled = 0;
bool wasFound = FALSE;
int *newElements = malloc(sizeof(int) * width * height);
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
wasFound = FALSE;
for (k = 0; k < maxFilled; k++) {
if (newElements[k] == array[i][j]) {
wasFound = TRUE;
break;
}
}
if (!wasFound) newElements[maxFilled++] = array[i][j];
}
}
/* Free space */
free(newElements);
return maxFilled;
}
int main ()
{
/* variables */
int i = 0, j = 0;
int originalWidth = 10;
int originalHeight = 10;
/* initialize array */
int **originalArray = (int **)malloc(originalHeight * sizeof(int*));
for (i = 0; i < originalHeight; i++) {
originalArray[i] = (int *)malloc(originalWidth * sizeof(int));
}
/* initialize random seed, then fill with random values */
srand (time(NULL));
for (i = 0; i < originalHeight; i++) {
for (j = 0; j < originalWidth; j++) {
originalArray[i][j] = rand() % 100;
}
}
printf("Number unique values: %d\n", NumberUniqueValues(originalArray, originalWidth, originalHeight));
/* Free space */
for (i = 0; i < originalHeight; i++) free(originalArray[i]);
free(originalArray);
return 0;
}
同样,对于您的情况,这可能不是最快的算法,因为我不知道所有细节,但它至少可以工作。祝你好运!
【讨论】:
首先,这取决于您对待阵列的方式。如果是动态的,可以把二维数组当作一维数组使用,因为静态二维数组是一维数组,动态数组可以创建为一维数组。
const int M = 100;
const int N = 200;
int **a = NULL;
int i, j;
a = (int**) malloc(M * sizeof(int*) + N * M * sizeof(int));
a[0] = (int*)(a + M);
for (i = 1; i < M; i++) {
a[i] = a[0] + i * N;
}
//code
free(a);
和
a[i][j] === a[0][i*num_of_columns + j]
所以,一维数组的 2 种算法
typedef int T;
#define EQ(a, b) ((a)==(b))
void quadDiff(T *a, size_t *out_size) {
size_t i, j;
size_t size = *out_size;
size_t pos = 0;
int unique;
for (i = 0; i < size; i++) {
unique = 1;
for (j = i; j > 0; j--) {
if (EQ(a[i], a[j-1])) {
unique = 0;
break;
}
}
if (unique) {
a[pos++] = a[i];
}
}
*out_size = pos;
}
和
void sortDiff(T *a, size_t item_size, size_t *out_size, int (*cmp)(const void *, const void *)) {
size_t i;
T prev = a[0];
size_t pos = 0;
qsort(a, *out_size, item_size, cmp);
for (i = 0; i < *out_size; i++) {
if (EQ(prev, a[i])) {
continue;
}
prev = a[i];
a[pos++] = a[i];
}
*out_size = pos;
}
【讨论】:
我会建议以下方法:
这个问题的时间复杂度是创建哈希图所需的时间。这不需要任何排序,并且比您使用的方法更有效。这种方法独立于输入数据的范围,使其更通用。
(我不擅长用 C 实现东西)我将包含一个演示该方法的 Java 代码。
class Distinct {
public static void main(String ar[]) {
int size;
int matrix[][] = new int[size][size];
// POPULATE THE MATRIX BY IMPLEMENTING CUSTOM METHOD
populate(matrix);
// ALGORITHM:
HashMap<Integer,Boolean> distinct = new HashMap<Integer,Boolean>();
for(int i=0;i<size;i++) {
for(int j=0;j<size;j++) {
distinct.put(matrix[i][j],true);
}
}
System.out.println("Number of distinct elements:"+distinct.size());
}
}
在 C 中实现哈希映射的指针可以在这里找到:Implementing a HashMap
我希望这会有所帮助!
【讨论】: