Home > Back-end >  Print elements of an array that appear only once (C)
Print elements of an array that appear only once (C)

Time:10-01

I am having trouble achieving the wanted results. The program should ask for 20 inputs and then go over each to see if they appear more than once. Then only print out those that appeared once.

However currently my program prints out random numbers that are not inputted.

For example: array = {10,10,11,12,10,10,10.....,10} should return 11 and 12

#include <stdio.h>


void main() {
    int count, size=20, array[size], newArr[size];
    int number=0;
    
    for(count = 0; count < size; count  ) {

        // Ask user for input until 20 correct inputs.
        printf("\nAnna %d. luku > ", count 1);
        scanf("%d", &number);

        if( (number > 100) || (number < 10) ) {
            
            while(1) {
                number = 0;
                printf("Ei kelpaa.\n");//"Is not valid"
                printf("Yrita uudelleen > ");//"Try again >"
                scanf("%d", &number);

                if ( (number <= 100) && (number >= 10) ) {
                    break;
                }
            }

        }
        array[count] = number;
    }
    for(int i=0; i < size; i  ) {

        for(int j=0; j<size; j  ){

            if(array[i] == array[j]){
                size--;
                break;

            } else {   
                // if not duplicate add to the new array
                newArr[i] == array[j];
            }
        }
    }
    // print out all the elements of the new array
    for(int k=0; k<size; k  ) {
        printf("%d\n", newArr[k]);
    }
}

CodePudding user response:

You don't need the newArr here, or the separate output loop. Only keep a count that you reset to zero at the beginning of the outer loop, and increase in the inner loop if you find a duplicate.

Once the inner loop is finished, and the counter is 1 then you don't have any duplicates and you print the value.

In code perhaps something like:

for (unsigned i = 0; i < size;   i)
{
    unsigned counter = 0;

    for (unsigned j = 0; j < size;   j)
    {
        if (array[i] == array[j])
        {
              counter;
        }
    }

    if (counter == 1)
    {
        printf("%d\n", array[i]);
    }
}

Note that the above is a pretty naive and brute-force way to deal with it, and that it will not perform very well for larger array sizes.

Then one could implement a hash-table, where the value is the key, and the count is the data.

Each time you read a value you increase the data for that value.

Once done iterate over the map and print all values whose data (counter) is 1.

CodePudding user response:

Use functions!! Use proper types for indexes (size_t).

void printdistinct(const int *arr, size_t size)
{
    int dist;
    for(size_t s = 0; s < size; s  )
    {
        int val = arr[s];

        dist = 1;
        for(size_t n = 0; n < size; n  )
        {
            if(s != n)
                if(val == arr[n]) {dist = 0; break;}
        }
        if(dist) printf("%d ", val);
    }
    printf("\n");
}


int main(void)
{
    int test[] =  {10,10,11,12,10,10,10,10};

    printdistinct(test, sizeof(test)/sizeof(test[0]));
    fflush(stdout);
}

https://godbolt.org/z/5bKfdn9Wv

CodePudding user response:

This approach uses some memory to keep track of which elements are duplicates. The memory cost is higher, but the processor time cost is lower. These differences will become significant at higher values of size.

char* duplicate = calloc(size); // values are initialized to zero

for (unsigned i = 0; i < size;   i)
{
    if(!duplicate[i]) // skip any value that's known to be a duplicate
    {
        for (unsigned j = i   1; j < size;   j) // only look at following values
        {
            if (array[i] == array[j])
            {
                duplicate[i] = 1;
                duplicate[j] = 1; // all duplicates will be marked
            }
        }

        if (!duplicate[i])
        {
            printf("%d\n", array[i]);
        }
    }
}

CodePudding user response:

What you can do is you can initialize a hashmap that will help you store the unique elements. Once you start iterating the array you check for that element in the hashmap. If it is not present in the hashmap add it to the hashmap. If it is already present keep iterating.

This way you would not have to iterate the loop twice. Your time complexity of the algorithm will be O(n).

unordered_map < int, int > map;
for (int i = 0; i < size; i  ) {
  // Check if present in the hashmap
  if (map.find(arr[i]) == map.end()) {
    // Insert the element in the hash map
    map[arr[i]] = arr[i];
    cout << arr[i] << " ";
  }
}
  • Related