C++ Array (disregarding a repeat number)

Viewed 1512

I am a beginner programmer and I need some assistance. I need to write a program that reads an array of 10 numbers from a user, then scans it and figures out the most common number/s in the array itself and prints them. If there is only one number that is common in the array, only print that number. But, if there's more than one number that appears more than once, print them also in the order they appear in in the array. For example- 1 2 3 3 4 5 6 7 8 9 - output would be 3 For- 1 2 3 4 1 2 3 4 5 6 - output would be 1 2 3 4 for- 1 1 1 1 2 2 2 3 3 4 - output would be 1 2 3

Now, the problem I've been running into, is that whenever I have a number that repeats more than twice (see third example above), the output I'm getting is the number of iterations of the loop for that number and not only that number once. Any assistance would be welcome.

Code's attached below-

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

int array [10], index, checker, common;
main ()
{

        for (index=0; index<10; index++)
        {
            cin >> array [index];
        }

        for (index=0; index<10; index++)
            {
                int tempcount=0;
                for (checker=(index+1);checker<10;checker++)
                    {   
                        if (array[index]==array[checker])
                            tempcount++;
                    }
                   if (tempcount>=1)
                   cout << array[index]<<" ";

            }

    return 0;
}
7 Answers

Use appropriate data structures for the task.

Create a std::unordered_map that maps value to number_of_occurrences, and make a single pass over the input data.

Then create another map from number_of_occurrences to value. Sort it, in descending order. Report the first value, plus any additional ones that occurred as many times as the first did.

Rather than writing you a solution, I will try to give you some hints that you can hopefully use to correct your code. Try to keep track of the following things:

  • Remember the position of the first occurrence of each distinct number in the array.
  • Count the number of times each number appears

and combine the two to get your solution.

EDIT:

int array[] = {1, 2, 3, 4, 1, 2, 3, 4, 5, 6};

int first [11], cnt[11];

for(int i = 0; i < 11; i++){
    first[i] = -1;
    cnt[i] = 0;
}

int max = 0;

for(int i = 0; i < 10; i++){
    cnt[array[i]]++;
    if(max < array[i]) max = array[i];
}   

for(int i = 0; i <= max; i++){
    if(cnt[i] > 1 && first[i] == -1) {
        printf(" %d", i);
        first[i] = i;   
    }
}

The reason you are having problems is that anytime a number appears two times or more it will print out. A solution is that you create another variable maxCount, then find the maximum times a number appears. Then loop through the array and print out all the numbers that appears the maximum amount of times.

Hope this helps.

Jake

You could do something like this. At any index in the array look for previous occurences of that element. If you find that that it is the first occurence of that element, you only need to look if there is an occurence of that element ahead in the array. Lastly display the element whose frequency(here num) would be greater than 1.

for (int i = 0; i < 10; i++)
{
    int presentBefore = 0;
    for (int j = 0; j < i; j++) //if any previous occurence of element
    {
        if (array[i] == array[j]) presentBefore++;
    }

    if (presentBefore == 0)//if first occurence of the element
    {
        int num = 1;
        for (int j = i + 1; j < 8; j++)// if occurences ahead in the array
        {
          if (array[i] == array[j]) num++;
        }
        if(num>1)cout<<array[i]<<" ";
    }
}

Here is another solution using STL and std::set.

#include <iostream>
#include <algorithm>
#include <set>
#include <iterator>

int main()
{

    int array[12] = { 1, 2, 3, 1, 2, 4, 5, 6, 3, 4, 1, 2 };
    std::set<int> dupes;

    for (auto it = std::begin(array), end = std::end(array); it != end; ++it)
    {
        if (std::count(it, end, *it) > 1 && dupes.insert(*it).second)
            std::cout << *it << " ";
    }

    return 0;
}

Prints:

1 2 3 4

I will try to explain how this works:

  1. The original array is iterated from start to finish (BTW as you can see it can be any length, not just 10, as it uses iterators of beginning and end)
  2. We are going to store duplicates which we find with std::count in std::set
  3. We count from current iterator until the end of the array for efficiency
  4. When count > 1, this means we have a duplicate so we store it in set for reference.
  5. std::set has unique keys, so trying to store another number that already exists in set will result in insert .second returning false.
  6. Hence, we print only unique insertions, which appear to be in the order of elements appearing in the array.

In your case you can use class std::vector which allows you to Erase elements, resize the array...

Here is an example I provide which produces what you wanted:

1: Push the values into a vector.

2: Use 2 loops and compare the elements array[i] and array[j] and if they are identical push the the element j into a new vector. Index j is always equal to i + 1 in order to avoid comparing the value with itself.

3- Now you get a vector of the repeated values in the temporary vector; You use 2 loops and search for the repeated values and erase them from the vector.

4- Print the output.

  • NB: I overloaded the insertion operator "<<" to print a vector to avoid each time using a loop to print a vector's elements.

The code could look like :

#include <iostream>
#include <vector>


std::ostream& operator << (std::ostream& out, std::vector<int> vecInt){
    for(int i(0); i < vecInt.size(); i++)
        out << vecInt[i] << ", ";
    return out;
}



int main() {

    std::vector< int > vecInt;
    //1 1 1 1 2 2 2 3 3 4 
    vecInt.push_back(1);
    vecInt.push_back(1);
    vecInt.push_back(1);
    vecInt.push_back(1);
    vecInt.push_back(2);
    vecInt.push_back(2);
    vecInt.push_back(2);
    vecInt.push_back(3);
    vecInt.push_back(3);
    vecInt.push_back(4);

    std::vector<int> vecUniq;

    for(int i(0); i < vecInt.size(); i++)
        for(int j(i + 1); j < vecInt.size(); j++)
            if(vecInt[i] == vecInt[j])
                vecUniq.push_back(vecInt[j]);

            std::cout << vecUniq << std::endl;

    for(int i = 0; i < vecUniq.size(); i++)
        for(int j = vecUniq.size() - 1 ; j >= 0 && j > i; j--)
            if(vecUniq[i] == vecUniq[j])
                vecUniq.erase(&vecUniq[j]);

            std::cout << vecUniq << std::endl;


    std::cout << std::endl;
    return 0;

}


The input:    1 2 3 3 4 5 6 7 8 9 
The output:   3

The input:    1 2 3 4 1 2 3 4 5 6
The output:   1 2 3 4

The input:    1 1 1 1 2 2 2 3 3 4
The output:   1 2 3

For this problem, you can use a marking array that will count the number of times you a digit is visited by you, it's just like counting sort. let's first see the program :

#include <iostream>
using namespace std;

int print(int a[],int b[])
{
    cout<<"b :: ";
    for (int index=0;index<10;index++)
    {
        cout<<b[index]<<"  ";
    }
    cout<<endl;
}

int main ()
{
    int a[10],b[11], index, checker, common;
        for (index=0; index<10; index++)
        {
            cin >> a [index];
            b[index] = 0;
        }
        b[10] =0;

        for (index=0;index<10;index++)
        {

            b[a[index]]++;
            if (b[a[index]] == 2)
                cout<<a[index];
            //print(a,b);
        }

    return 0;
}

As you can see that I have used array b as marking array which counts the time a number is visited. The size of array b depends upon what is the largest number you are going to enter, I have set the size of array b to be of length 10 that b[11] as your largest number is 10. Index 0 is of no use but you need not worry about it as it will be not pointed until your input has 0.

Intially all elements in array in b is set 0. Now assume your input to be :: 1 2 3 4 1 2 3 4 5 6

Now value of b can be checked after each iteration by uncommenting the print function line::

b :: 0  1  0  0  0  0  0  0  0  0     ....1
b :: 0  1  1  0  0  0  0  0  0  0     ....2
b :: 0  1  1  1  0  0  0  0  0  0     ....3
b :: 0  1  1  1  1  0  0  0  0  0     ....4
b :: 0  2  1  1  1  0  0  0  0  0     ....5
b :: 0  2  2  1  1  0  0  0  0  0     ....6
b :: 0  2  2  2  1  0  0  0  0  0     ....7
b :: 0  2  2  2  2  0  0  0  0  0     ....8
b :: 0  2  2  2  2  1  0  0  0  0     ....9
b :: 0  2  2  2  2  1  1  0  0  0     ....10

In line 5 you can b's at index 1 has value 2 so it will print 1 that is a[index].

And array a's element will be printed only when it is repeated first time due to this line if(b[a[index]] == 2) .

This program uses the idea of counting sort so if you want you can check counting sort.

Related