Home > Net >  Find how many times numbers appear in array
Find how many times numbers appear in array

Time:03-05

My program should print how many times each number appears in array.

OUTPUT:

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

This is my output:

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

Could you help me fix my code?

CodePudding user response:

Another way to do the same

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

CodePudding user response:

Try this (see below). One of your main problems is that you are using counter[i] but that is using a loop index, not the actual number from the array. So you need to use counter[arr[i]]. The other problem is that you are using two nested loops, which will double up your counts.

Note: The quicksort compare function is taken from 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);
}

Output:

---------- 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.

CodePudding user response:

Using an array such as int counts[1000]; is going to limit the integers you can track into the range [0, 999] (that is, greater-than or equal to 0, and less-than or equal to 999). This is fine, as long as you can guarantee each input value is within this range (or otherwise handle values outside the range).

There is no need for a nested loop; simply increment the frequency counter for your current value, and update your maximum if this new count exceeds it.

When it comes time to print: for small ranges, you can just scan it entirely for hits,

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

or if performance is a concern, you can sort the array, and only print each value once by resetting the frequency afterwards. Again, you must watch for values outside the valid range.

#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

As we've seen, using an array limits the range of integers you can support. Data structures other than arrays can provide an alternative solution to this problem.

One suggestion would be to use a linked list, so that you can support the entire range of a signed type (in this case, [INT_MIN, INT_MAX]).

Here we add our value to the list with a count of 1 if it has not been seen, otherwise we increment the existing count.

#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("d appears d times.", n->value, n->count);

        if (n->count == min)
            printf(" (MIN)");

        if (n->count == max)
            printf(" (MAX)");

        putchar('\n');

        t = n->next;
        free(n);
    }
}

Output:

      -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)

With this implementation, presorting your input (high-to-low) may provide performance benefits. In any case, this list will sort itself as it is built. This side effect may be desirable in situations where your input cannot be sorted ahead of time.

  • Related