查找一维数组的不同元素数量的最快和最有效的方法
Posted
技术标签:
【中文标题】查找一维数组的不同元素数量的最快和最有效的方法【英文标题】:The fastest and most efficient way to find the number of distinct elements of a 1D array 【发布时间】:2022-01-15 02:19:15 【问题描述】:所以我对编程和 C 语言非常陌生,我想找到最简单、最快和最有效的方法来计算一维数组的所有不同元素。这实际上是为了学校作业,但我已经被这个问题困扰了好几天,因为我的程序对于在线法官来说显然太慢了,而且它得到了 TLE。我使用过常规数组和使用 malloc 动态分配的数组,但都不起作用。
无论如何,这是它的最新代码(使用 malloc):
#include <stdio.h>
#include <stdlib.h>
int distinct(int *arr, int N)
int j, k, count = 1;
for(j = 1; j < N; j++)
for(k = 0; k < j; k++)
if(arr[j] == arr[k])
break;
if(j == k)
count++;
return count;
int main()
int T, N, i = 0;
scanf("%d", &T);
do
scanf("%d", &N);
int *arr;
arr = (int*)malloc(N * sizeof(int));
for(int j = 0; j < N; j++)
scanf("%d", &arr[j]);
int count = distinct(arr, N);
printf("Case #%d: %d\n", i + 1, count);
i++;
while(i < T);
return 0;
【问题讨论】:
对数组进行排序并检查是否有两个相同的连续元素 所以我对编程和 C 语言还很陌生 然后完全不用担心找到“[t]最快和最有效的方法”来做任何事情.了解如何编写既可读又可维护的代码,这样当您在两周内再次看到您编写的代码时,您不必花费 30 分钟来弄清楚编写它的白痴想要做什么。 你允许多大的值,int
可以保持任何值还是可以限制在某个范围内?
不,正如我所写,您允许数组包含哪些值?例如,如果它们被限制在 0 到 100 之间,您可以制作一个计数器表,其中索引对应于某个遇到的值。但如果它们可以是 +/- 2^31 的任何值,那么这样的解决方案是不可行的。
你的实际目标不是找到最快的方法。这很困难,取决于处理器架构和特性以及其他因素。您的实际目标是使程序足够快以满足在线评委的要求。方法可能很简单:对数组进行排序。这将使相同的元素彼此相邻。然后查看数组,检查任何两个相邻元素是否相同。排序应该是 O(n log n),这意味着它所采取的步数与 n 乘以 log n 成正比,其中 n 是数组中的元素数……
【参考方案1】:
最有效的方法取决于太多未知因素。一种方法是对数组进行排序,然后计算其中的不同元素,同时跳过重复的元素。如果你已经对数组进行了排序并得到了这个:
1 1 1 1 2 2 2 2 3 3
^ ^ ^
+-skip--+-skip--+-- end
...您可以很容易地看到其中有 3 个不同的值。
如果您手边没有喜欢的排序算法,可以使用内置的qsort
函数:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
例子:
#include <stdio.h>
#include <stdlib.h>
int compar(const void *l, const void *r)
const int* lhs = l;
const int* rhs = r;
if(*lhs < *rhs) return -1; // left side is less than right side: -1
if(*lhs > *rhs) return 1; // left side is greater than right side: 1
return 0; // they are equal: 0
int distinct(int arr[], int N)
// sort the numbers
qsort(arr, N, sizeof *arr, compar);
int count = 0;
for(int i=0; i < N; ++count)
int curr = arr[i];
// skip all numbers equal to curr as shown in the graph above:
for(++i; i < N; ++i)
if(arr[i] != curr) break;
return count;
int main()
int T, N, i = 0;
if(scanf("%d", &T) != 1) return 1; // check for errors
while(T-- > 0)
if(scanf("%d", &N) != 1) return 1;
int *arr = malloc(N * sizeof *arr);
if(arr == NULL) return 1; // check for errors
for(int j = 0; j < N; j++)
if(scanf("%d", &arr[j]) != 1) return 1;
int count = distinct(arr, N);
free(arr); // free after use
printf("Case #%d: %d\n", ++i, count);
【讨论】:
for(++i; i < N; ++i)
给了我过敏反应 :) for(int j=i+1; j<N; j++)
... arr[j]
怎么样?
@Lundin :-D 好吧,这意味着我必须在循环之外声明 j
并在之后将 i
分配给它。 int j = i + 1; for(;j<N; ++j) ... i = j;
- 不确定这会变得更清楚。这是i
索引,我想向前跳过直到遇到新数字,并且我希望外循环的下一次迭代使用该i
以上是关于查找一维数组的不同元素数量的最快和最有效的方法的主要内容,如果未能解决你的问题,请参考以下文章