【问题标题】:A program that counts unique elements in an un-ordered array计算无序数组中唯一元素的程序
【发布时间】:2015-04-17 20:41:17
【问题描述】:
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)

【问题讨论】:

  • 好吧,我正在尝试创建一个函数,在该函数中计算数组中的所有唯一元素。例如 a[1,4,2,6,6,7,8,5,5,4],这个 aray 将有 7 个唯一元素。我的程序会找到数组的最大值,然后进行比较以计算唯一元素...但是它有问题,当您输入数组但跳过一个数字(例如 1,2,4,5 ,它不会计数所有唯一的数字......我不知道它有什么问题。
  • 您只有在找到匹配项时才减少max,当您的序列中有漏洞时您不会这样做。例如:您的测试向量将找到 8、7、6 和 5,但由于没有 4,max 永远不会被调整为寻找 321,并且最终会出现双循环以您找到的四个项目的总和结束。

标签: c arrays unique counter elements


【解决方案1】:

有时简单的规则。

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())。它也不会尝试计算最大或重复次数,或类似的东西。

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

【讨论】:

  • int arrint *arr 更有意义,甚至更好const int *arr
【解决方案2】:

只是让您知道,@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;
}

【讨论】:

    【解决方案3】:

    这应该工作..用这个替换第二个for循环集。

    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 
    

    【讨论】:

    • 谢谢,但这只是计算所有元素而不是唯一元素。
    • int arr[] = {1,2,2,5,6,7,8,3,9,1}; int dis_num = num_distinct(arr,10);输出是 8 而不是 7 ..
    • 不应该是6吗??因为 2 和 1 不是唯一的
    • 2 和 1 的出现次数超过 1 次
    • 它工作得非常好,非常感谢^.^我不敢相信我错过了我整天编码的事情,必须获得隧道视野..再次感谢!!!!
    【解决方案4】:

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

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

    #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;
    }
    

    【讨论】:

    • flag = (int*)malloc(n); 分配太小。使用flag = malloc(sizeof *flag * n);
    猜你喜欢
    • 1970-01-01
    • 2012-04-28
    • 2013-11-30
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    相关资源
    最近更新 更多