Most occuring digit in an array of numbers I stumbled upon this exercise , and I am wondering if there is a more efficient way of writing this. It is written from high school level knowledge.


  Find the most occuring number of an array of numbers, with each number only counting one per number. For example in 2222 the 2 only counts ONCE. If you have 2 or more digits with the same amount of occurrences write out a random one. For example X[3] = {20; 21; 30}, either write out 0 or 2.


I could've used dynamic arrays, but that's not what I'm interested in here.

#include &lt;iostream&gt;
#include &lt;time.h&gt;
#include &lt;stdlib.h&gt;

using namespace std;

struct numbers
{
int number;
int howmany;
};

int main()
{
int X[20], Z[9], sizex, i, j, temp, howmany_found = 0, howmany_elem = 0, max = 0;
numbers Y[10];
bool found;

srand(time(NULL));

cout &lt;&lt; "Array size: " ;
cin &gt;&gt; sizex;

for (i = 0; i &lt; sizex; i++)
{
    cout &lt;&lt; i + 1 &lt;&lt; " element: " &lt;&lt; " " ;
    cin &gt;&gt; X[i];
}

for (i = 0; i &lt;= 9; i++)
{
    Y[i].number = i;
}

for (i = 0; i &lt;= 9; i++)
{
    for (j = 0; j &lt; sizex; j++)
    {
    found = false;
    temp = X[j];

    while (found != true &amp;&amp; temp &gt;= 1)
    {
        if (temp % 10 == i)
        {
            found = true;
            howmany_found++;

        }
        temp /= 10;
    }
    }
    Y[i].howmany = howmany_found;
    howmany_found = 0;
}

for (i = 0; i &lt;= 9; i++)
{
    if (Y[i].howmany &gt; max)
        max = Y[i].howmany;

    if (Y[i].howmany &gt; 0)
    cout &lt;&lt; "(" &lt;&lt; Y[i].number &lt;&lt; "," &lt;&lt; Y[i].howmany &lt;&lt; ")" ;
}

for (i = 0; i &lt;=9; i++)
{
    if (Y[i].howmany == max)
    {
        Z[howmany_elem] = Y[i].number;
        howmany_elem++;
    }
}

if (howmany_elem &gt; 1)
{
int RandIndex = rand() % howmany_elem ;
cout &lt;&lt; endl;
cout &lt;&lt; Z[RandIndex] ;
}
else
{
    cout &lt;&lt; endl;
    cout &lt;&lt; Z[0] ;
}

return 0; 
}
Outer loop unnecessary
If there are N numbers, each with M digits, your solution is using 10 * N * M operations to compute the solution.  This is because for each digit (e.g. 0, 1, 2), you look at every digit in every number.  But you could make your solution 10 times faster by only looking at each digit once.  All you need to do is to track duplicate digits for each new number.
Here is how that would work:
for (i = 0; i &lt;= 9; i++)
{
    Y[i].number = i;
    Y[i].howmany = 0;
}

for (i = 0; i &lt; sizex; i++)
{
    int foundDigits = 0;

    for (int curNumber = X[i]; curNumber &gt; 0; curNumber /= 10) {
        int digit = curNumber % 10;
        int bit   = 1 &lt;&lt; digit;

        if ((foundDigits &amp; bit) == 0) {
            foundDigits |= bit;
            Y[digit].howmany++;
        }
    }
}

Here, foundDigits is a bitmask which contains a 1 bit for each digit already seen in the current number.  This is what is used to track duplicate digits.  When a non-duplicate digit is seen, we can just increment the Y[digit].howmany array directly.
struct numbers unnecessary
Actually, the numbers structure is unnecessary because Y[i].number is always equal to i.  So you can just have Y be an array of integers holding the count of each digit.  Wherever you currently use Y[i].number, just replace that with i instead.