You can check the Optimised algorithm analysis and implementation here.
The brute-force solution is highly inefficient because it checks each integer sequentially and factors every single number using unoptimized trial division.
-
get_prime_factors(num): In the worst-case scenario (whennumis prime), the loop must increment the divisor all the way up tonum, resulting in a time complexity of$O(\text{num})$ . -
is_square_num(num): Inherits the$O(\text{num})$ worst-case complexity due to calling the prime factorization step. -
generate_k_square_nums(k): The algorithm tests every integer up to a maximum iteration limit$m$ . Because it performs an$O(i)$ factorization check on every integer$i$ from$1$ to$m$ , the total workload is the sum of arithmetic progressions ($\sum_{i=1}^{m} i$ ), yielding an implementation complexity of$O(m^2)$ .
Since the
Although the number of squares found grows sub-linearly at a rate of
According to our definitive execution benchmarks, the algorithm scales terribly under this
- At
k = 10($m = 100$ ), it completes in 0.318 seconds. - At
k = 100($m = 10,000$ ), it completes in 0.774 seconds. - At
k = 1000($m = 1,000,000$ ), the computation hits the complexity wall, taking 2.25 hours (8,098.075 seconds) to complete.
This sandbox perfectly illustrates why infrastructure optimizations (like multi-processing) cannot save a program from poor algorithmic complexity.