【问题标题】:Find how many times numbers appear in array找出数字在数组中出现的次数
【发布时间】:2022-03-05 06:19:34
【问题描述】:

我的程序应该打印每个数字在数组中出现的次数。

输出:

数字 1 出现 2 次
数字 2 出现 5 次
数字 3 出现 1 次
数字 4 出现 3 次
最频繁:2

这是我的输出:

Number 1 appears 1 times
Number 2 appears 4 times
Number 1 appears 0 times
Number 4 appears 2 times
Number 2 appears 3 times
Number 4 appears 1 times
Number 2 appears 2 times
Number 2 appears 1 times
Number 3 appears 0 times
Number 4 appears 0 times
Number 2 appears 0 times
Most frequent: 2
#include <stdio.h>

void main() {
    int i, j, count = 0, max_count = 0, max, n;
    int arr[] = { 1, 2, 1, 4, 2, 4, 2, 2, 3, 4, 2 }, counter[1000] = { 0 };
    n = sizeof(arr) / sizeof(*arr);

    for (i = 0; i < n; i++) {
        count = 0;

        for (j = i + 1; j < n; j++) {
            if (arr[i] == arr[j]) {
                count++;
                counter[i]++;
            }
            if (count > max_count) {
                max = arr[j];
                max_count = count;
            }
        }
    }

    for (i = 0; i < n; i++)
        printf("Number %d appears %d times\n", arr[i], counter[i]);

    printf("Most frequent: %d\n", max);
}

你能帮我修复我的代码吗?

【问题讨论】:

  • 提示:你不需要两个循环。
  • @Wyck 我的错误,它应该从 i 开始,或者 count 一开始应该是 = 1
  • 有两个问题。一,您的计数减少了 1,因为您正在计算元素的重复数,不包括元素本身。解决此问题的最简单方法是将for (j = i + 1; 替换为for (j = i;。第二个更难:您还打印每个元素的第二个、第三个等副本的计数。你想跳过那些。我会让你弄清楚怎么做,但这里有一个提示:如果arr[i] == arr[j]i != j,那么你想跳过输出中的jth 元素。您也可以考虑另一种计算重复项的方法(例如,首先对数组进行排序的方法)。

标签: arrays c


【解决方案1】:

另一种方法

#include <stdio.h>

int main(void) {
    int arr[] = { 1, 2, 1, 4, 2, 4, 2, 2, 3, 4, 2 };
    
    for ( int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i ) {
        // look if this value meets above
        int j, count = 1;
        for ( j = 0; j < i; ++j )
            if ( arr[j] == arr[i] )
                break;
        // if number already counted just skip it
        if ( j < i )
            continue;
        for ( j = i + 1; j < sizeof(arr) / sizeof(arr[0]); ++j )
            if ( arr[j] == arr[i] )
                count += 1;
        printf("Number %d appears %d times\n", arr[i], count);
    }

    return 0;
}

【讨论】:

    【解决方案2】:

    试试这个(见下文)。您的主要问题之一是您使用的是counter[i],但这是使用循环索引,而不是数组中的实际数字。所以你需要使用counter[arr[i]]。另一个问题是您使用了两个嵌套循环,这会使您的计数加倍。

    注意:快速排序比较函数取自this answer

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int compare( const void* a, const void* b)
    {
         int int_a = * ( (int*) a );
         int int_b = * ( (int*) b );
    
         if ( int_a == int_b ) return 0;
         else if ( int_a < int_b ) return -1;
         else return 1;
    }
    
    int main()
    {
      int i, j, count = 0, max_count = 0, max, n;
      int arr[] = {1, 2, 1, 4, 2, 4, 2, 2, 3, 4, 2}, counter[1000] = {0};
      n = sizeof(arr) / sizeof(*arr);
      qsort( arr, n, sizeof(int), compare );
      for (i = 0; i < n; i++) {
        ++counter[arr[i]];
      }
      max = 0;
      for (i = 0; i < n; i++) {
        if (counter[arr[i]] > max) {
          max = arr[i];
        }
      }
      
      int seen[1000];
      memset(seen,0,sizeof seen);
      for (i = 0; i < n; i++) {
        if (seen[arr[i]])
          continue;
        seen[arr[i]] = 1;
        printf("Number %d appears %d times\n", arr[i], counter[arr[i]]);
      }
      printf("Most frequent: %d\n", max);
    }
    

    输出:

    ---------- Capture Output ----------
    > "c:\windows\system32\cmd.exe" /c C:\Temp\temp.exe
    Number 1 appears 2 times
    Number 2 appears 5 times
    Number 3 appears 1 times
    Number 4 appears 3 times
    Most frequent: 4
    
    > Terminated with exit code 0.
    

    【讨论】:

    • 编译时遇到一些错误
    • @devec - 现在应该可以在 C 中工作了
    • 非常感谢
    • 如果您知道数组的所有元素都是 0 到 1000 之间的整数,这是一个好方法。
    • @dcp:只有当计数为&gt; 0 时,您才会打印出现次数,并在打印第一次出现后立即将其重置为0。将不再打印每次出现的情况。如果你想保留数字,你可以用同样的效果否定计数。
    【解决方案3】:

    使用int counts[1000]; 之类的数组会将您可以跟踪的整数限制在[0, 999] 范围内(即大于或等于0,小于或等于999 )。这很好,只要您可以保证每个输入值都在此范围内(或以其他方式处理范围外的值)。

    不需要嵌套循环;只需为您的当前值增加频率计数器,如果这个新计数超过它,则更新您的最大值。

    当需要打印时:对于小范围,您可以完全扫描它以查找命中,

    for (size_t i = 0; i < MAX_N; i++)
        if (freq[i])
            printf("Number %zu appears %d times\n", i, freq[i]);
    

    或者如果性能是一个问题,您可以对数组进行排序,然后通过重置频率只打印一次每个值。同样,您必须注意有效范围之外的值。

    #include <limits.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_N 1000
    
    int low_to_high(const void *p1, const void *p2) {
        int a = *((int *) p1),
            b = *((int *) p2);
    
        return a == b ? 0 : a > b ? 1 : -1;
    }
    
    int main(void) {
        int input[] = { 1, 2, 1, 4, 2, 4, -5, 2, 2, 3, 4, 2, 1000 };
        size_t input_length = sizeof input / sizeof *input;
    
        int freq[MAX_N] = { 0 };
        int max_value, max_freq = INT_MIN;
    
        for (size_t i = 0; i < input_length; i++) {
            int value = input[i];
    
            if (value >= MAX_N || value < 0) {
                fprintf(stderr, "Stray value detected: %d\n", value);
                continue;
            }
    
            if (++freq[value] > max_freq) {
                max_freq = freq[value];
                max_value = value;
            }
        }
    
        qsort(input, input_length, sizeof *input, low_to_high);
    
        for (size_t i = 0; i < input_length; i++) {
            int value = input[i];
    
            if (value >= MAX_N || value < 0) {
                fprintf(stderr, "Stray value detected: %d\n", value);
                continue;
            }
    
            if (freq[value]) {
                printf("Number %d appears %d times\n", value, freq[value]);
                freq[value] = 0;
            }
        }
    
        printf("Most frequent: %d [%d]\n", max_value, max_freq);
    }
    
    

    stdout:

    Number 1 appears 2 times
    Number 2 appears 5 times
    Number 3 appears 1 times
    Number 4 appears 3 times
    Most frequent: 2 [5]
    

    stderr:

    Stray value detected: -5
    Stray value detected: 1000
    Stray value detected: -5
    Stray value detected: 1000
    

    正如我们所见,使用 数组 会限制您可以支持的整数范围。 数组以外的数据结构可以为这个问题提供另一种解决方案。

    一个建议是使用链表,这样您就可以支持带符号类型的整个范围(在本例中为[INT_MIN, INT_MAX])。

    这里我们将我们的值添加到列表中,如果它没有被看到,则计数为1,否则我们增加现有的计数。

    #include <limits.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    struct freq {
        int value;
        int count;
        struct freq *next;
    };
    
    struct freq_list {
        struct freq *head;
    };
    
    struct freq *freq_create(int value, struct freq *next) {
        struct freq *node = malloc(sizeof *node);
    
        node->value = value;
        node->count = 1;
        node->next = next;
    
        return node;
    }
    
    int freq_list_increase(struct freq_list *list, int value)
    {
        if (!list->head || list->head->value > value)
            list->head = freq_create(value, list->head);
        else {
            struct freq *node = list->head;
            struct freq *last = NULL;
    
            while (node && node->value < value) {
                last = node;
                node = node->next;
            }
    
            if (!node || node->value > value)
                last->next = freq_create(value, node);
            else
                return ++node->count;
        }
    
        return 1;
    }
    
    int main(void) {
        int array[] = { 1, 2, 1, 4, 2, 4, 2, 2, 3, 4, 2, -1, -1, -1273, 7473, 0, 0, -2000 };
        size_t array_length = sizeof array / sizeof *array;
    
        struct freq_list counts = { NULL };
        int min = INT_MAX;
        int max = INT_MIN;
    
        for (size_t i = 0; i < array_length; i++) {
            int val = freq_list_increase(&counts, array[i]);
    
            if (val < min)
                min = val;
    
            if (val > max)
                max = val;
        }
    
        for (struct freq *t = NULL, *n = counts.head; n; n = t) {
            printf("%11d appears %11d times.", n->value, n->count);
    
            if (n->count == min)
                printf(" (MIN)");
    
            if (n->count == max)
                printf(" (MAX)");
    
            putchar('\n');
    
            t = n->next;
            free(n);
        }
    }
    

    输出:

          -2000 appears           1 times. (MIN)
          -1273 appears           1 times. (MIN)
             -1 appears           2 times.
              0 appears           2 times.
              1 appears           2 times.
              2 appears           5 times. (MAX)
              3 appears           1 times. (MIN)
              4 appears           3 times.
           7473 appears           1 times. (MIN)
    

    通过此实现,对您的输入进行预排序(从高到低)可能会带来性能优势。在任何情况下,此列表都会在构建时自行排序。在您的输入无法提前排序的情况下,这种副作用可能是可取的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-14
      • 2017-07-26
      • 1970-01-01
      相关资源
      最近更新 更多