一个计算无序数组中唯一元素的程序

时间:2015-02-17 07:19:37

标签: c arrays unique counter elements

int num_distinct(int a[], int n)
{
  int i, k, j, count=0;
  int max = a[0];

  for (i = 1; i < n; i++) {
    if (max < a[i]) {
      max = a[i];
    }
  }
  for (k = 0; k < n; ++k) {
    for (j = 0; j < n; ++j) {
      if (a[j] == max) {
        ++count;
        --max;
        break;
      }
    }
  }
  return (count);
}

我试图做的是找到数组中的最大值并将其与数组中其余元素进行比较。它工作,但当数组跳过一个数字,即(1,2,2,5,6,7,8)&lt; - 它跳过3和4.我的代码将只计数8,7,6,5返回4个独特的数字。

4 个答案:

答案 0 :(得分:3)

只是为了让你知道,@ kcDod的算法是有缺陷的。它不计算这样的元素:1,2,3,4,9000,4,2 尝试,你会看到:

下面的代码无论元素如何都会计数,并且需要的功率要少得多,你不会通过递增或递减数组中的最大值来计算唯一元素,我不知道你在哪里有这个想法。

int unique_elements(int arr[], int len) {

    int counted[len], j, n, count, flag;

    counted[0] = arr[0]; 

    count = 1;/*one element is counted*/

        for(j=0; j <= len-1; ++j) {
        flag = 1;;
        /*the counted array will always have 'count' elements*/
        for(n=0; n < count; ++n) {
            if(arr[j] == counted[n]) {
                flag = 0;
            }
        }
        if(flag == 1) {
            ++count;
            counted[count-1] = arr[j];
        }
    }
    return count;
}


int main(void) {
    int arr[13] = {1, 2, 2, 123121, 123121, 3, 5, 6 , 7, 7, 14, 2, 16};
    printf("%d", unique_elements(arr, 13));
    return 0;
}

答案 1 :(得分:2)

这应该工作..用这个替换第二个循环设置。

int flag = 0; // We need to flag that we found a max in the iteration. So don't count again

for (k = 0; k < n;){
     for (j = 0; j < n; ++j) {         
          if (a[j] == max){
             if (flag==0){
                 ++count; // We count an occurrence only once 
                 flag = 1;
              }
             k++; // We should decrease the search when we found an element from original array
          }
      }
    // Reset parameters
    --max;
    flag = 0;
}

一个工作示例:

#include <stdio.h>

int main()
{
    int a[7] = { 7,2,2,4,5,6,7};
    int n = 7; // Number of elements in the array 

    int max=0;
    int i, k, j=0;

    for (i = 1; i < n; i++)
    {
        if (max < a[i])
         {
            max = a[i];
        }
    }

    int count=0;
    int flag = 0;

    for (k = 0; k < n;)
    {
        for (j = 0; j < n; ++j)
        {
            if (a[j] == max)
            {
                if (flag==0)
                {
                    ++count;
                    flag = 1;
                }
             k++;
         }
        }
        --max;
         flag = 0;
    }

    printf("Unique elements : %d\n",count);
}

输出:

Unique elements : 5 

答案 2 :(得分:2)

有时简单规则。

int unique_elements(int arr, int len)
{
     if (len <= 0) return 0;
     int unique = 1;

     for (int outer = 1; outer < len; ++outer)
     {
        int is_unique = 1;
        for (int inner = 0; is_unique && inner < outer; ++inner)
        {  
             if (arr[inner] == arr[outer]) is_unique = 0;
        }
        if (is_unique) ++unique;
     }
     return unique;
}

逻辑是外部循环选择要测试的值,内部循环检查所有先前的值。如果找到该值,则它不是唯一的,因此计数会递增。

这样做的好处是不使用临时存储(无论是VLA,还是使用malloc())。它也不会尝试计算最大值,重复次数或类似数量。

最坏的情况是执行时间是所有值都是唯一的(即数组中没有重复的值)。

答案 3 :(得分:0)

当数组中的最大值非常大时,您的算法可能需要更长的时间。记住哪个元素已被计算似乎已经更好,以降低计算复杂性。

下面的代码会记住哪些元素已被计算,如果已经计算了元素,则会跳过计算元素的数量。我使用一个标志数组来记住计数元素。

#include <stdlib.h>

int num_distinct(int a[], int n) {
    int* flag;
    int all_counted = 0;
    int i, cur, count = 0;
    int cur_flag;

    flag = (int*)malloc(n);
    for (i = 0; i < n; i++) flag[i] = 0;

    while (all_counted == 0) {
        cur_flag = 0;
        for (i = count; i < n; i++) {
            if (cur_flag == 0 && flag[i] == 0) {
                flag[i] = 1;
                cur_flag = 1;
                cur = a[i];
                count++;
            } else if (cur_flag == 1 && cur == a[i]) {
                flag[i] = 1;
            }
        }
        if (cur_flag == 0) all_counted = 1;
    }
    free(flag);
    return count;
}