Your algorithm is O(n^3)
.
You have two nested loops, and inside you use factorial()
, having O(n)
complexity itself.
Your algorithm tests all (n,m)
combinations, even those where factorial(n)
and m^2
are far apart, e.g. n=1
and m=10000
.
You always recompute the factorial(n)
deep inside the loop, although it's independent of the inner loop variable m
. So, it could be moved outside of the inner loop.
And, instead of always computing factorial(n)
from scratch, you could do that incrementally. Whenever you increment n
by 1
, you can multiply the previous factorial by n
.
A different, better approach would be not to use nested loops, but to always keep n
and m
in a number range so that factorial(n)
is close to m^2
, to avoid checking number pairs that are vastly off. We can do this by deciding which variable to increment next. If the factorial is smaller, then the next brocard pair needs a bigger n
. If the square is smaller, we need a bigger m
.
In pseudo code, that would be
n = 1; m = 1; factorial = 1;
while n < 10000 and m < 10000
if factorial + 1 == m^2
found a brocard pair
// the next brocard pair will have different n and m,
// so we can increment both
n = n + 1
factorial = factorial * n
m = m + 1
else if factorial + 1 < m^2
// n is too small for the current m
n = n + 1
factorial = factorial * n
else
// m is too small for the given n
m = m + 1
In each loop iteration, we either increment n
or m
, so we can have at most 20000 iterations. There is no inner loop in the algorithm. We have O(n)
. So, this should be fast enough for n
and m
up to the millions range.
P.S. There are still some optimizations possible.
Factorials (after n=1, known to have no brocard pair) are always even numbers, so m^2 must be odd to satisfy the brocard condition, meaning that we can always increment m by 2, skipping the even number in between.
For larger n
values, the factorial increases much faster than the square. So, instead of incrementing m
until its square reaches the factorial+1
value, we could recompute the next plausible m
as integer square root of factorial+1
.
Or, using the square root approach, just compute the integer square root of factorial(n), and check if it matches, without any incremental steps for m.