【问题标题】: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 是数组中的元素数……

标签: arrays c malloc


【解决方案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 &lt; N; ++i) 给了我过敏反应 :) for(int j=i+1; j&lt;N; j++) ... arr[j] 怎么样?
  • @Lundin :-D 好吧,这意味着我必须在循环之外声明 j 并在之后将 i 分配给它。 int j = i + 1; for(;j&lt;N; ++j) {...} i = j; - 不确定这会变得更清楚。这是i 索引,我想向前跳过直到遇到新数字,并且我希望外循环的下一次迭代使用该i
猜你喜欢
  • 2013-12-26
  • 1970-01-01
  • 2020-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-16
  • 2013-06-14
  • 2019-07-07
相关资源
最近更新 更多