g.d.d.c's solution is slightly redundant in that it checks numbers that are multiples of 3 and 5 twice. I was wondering about optimizations to this, so this is slightly longer than a comment, but not really an answer in itself, as it totally relies on g.d.d.c's awesome answer as inspiration.
If you add multiples to the valid list for the multiple "3" and then do another pass over the whole list (1-1000) for the multiple "5" then you do experience some redundancy.
The order in which you add them:
add 3-multiples first
add 5 multiples second
will matter (albeit slightly) if you want to check if the number exists in the list or not.
That is, if your algorithm is something like
add 3-multiples to the list
add 5-multiples to the list if they don't collide
it will perform slightly worse than
add 5-multiples to the list
add 3-multiples to the list if they don't collide
namely, because there are more 3-multiples than 5-multiples, and so you are doing more "if they don't collide" checks.
So, here are some thoughts to keep in mind, in terms of optimization:
- It would be best if we could iterate through the list once
- It would be best if we didn't check numbers that weren't multiples of 3 nor 5.
One possible way is to notice the frequency of the multiples. That is, notice that the LCM (least-common multiple) of 3 and 5 is 15:
3 6 9 12 15 18 21 24 27 30
|| ||
5 10 15 20 25 30
Thus, you should want to, in the optimal case, want to use the frequency representation of multiples of 3 and 5 in the range (1,15) over and over until you reach 1000. (really 1005 which is divided by 15 evenly 67 times).
So, you want, for each iteration of this frequency representation:
the numbers at: 3 5 6 9 10 12 15
Your frequencies occur (I'm sorta making up the vocab for this, so please correct me if there are better math-y words) at starting indexes from 0k + 1 to 67k (1 to 1005) [technically 66k]
And you want the numbers at positions 3, 5, 6, 9, 10, 12, and 15 enumerating from the index.
Thus,
for (freq_index = 0; freq_index < 66; ++freq_index) {
valid.add(15*freq_index + 3);
valid.add(15*freq_index + 5);
valid.add(15*freq_index + 6);
valid.add(15*freq_index + 9);
valid.add(15*freq_index + 10);
valid.add(15*freq_index + 12);
valid.add(15*freq_index + 15); //also the first term of the next indexed range
}
and we have eliminated redundancy
=)
Exercise for the astute / determined programmer:
Write a function that takes three integers as arguments,
x y z and, without redundancy, finds all the multiples of
x and of
y in the range from 1 to
z.
(basically a generalization of what I did above).