The challenge
Given array a of n numbers, I need to count how many positive numbers less than each aᵢ have exactly 3 divisors.
Constraints
1 <= aᵢ <= 2.5 * 10¹³
In other words,
- the minimum value is 1, and
- the maximum value is 25,000,000,000,000.
Example
Input
[100, 15, 30, 10]
Output
[4, 2, 3, 2]
Explanation
- range 1-100 has 4 numbers each having three divisors (4, 9, 25, 49).
- range 1-15 has 2 such numbers (4, 9).
- range 1-30 has 2 such numbers (4, 9, 25).
- range 1-10 has 2 such numbers (4, 9).
Notice that all the matching numbers are squares of prime numbers:
- 4 = 2²
- 9 = 3²
- 25 = 5²
- 49 = 7²
The code
function square_of_primes($limit) {
$result = array();
for ($i = 2; $i * $i < $limit; $i++) {
$is_prime = true;
for ($j = 2; $j * $j <= $i; $j++) {
if ($i % $j === 0) {
$is_prime = false;
break;
}
}
if ($is_prime) {
$result[] = $i * $i;
}
}
return count($result);
}
function findDivisors($arr) {
$result = [];
foreach ($arr as $num) {
$result[] = square_of_primes($num);
}
return $result;
}
$arr = [100,10, 30];
$divisors = findDivisors($arr);
echo "<pre>";
print_r( $divisors );
Concerns
Whilst this code gives correct answers for small arrays containing small values, it scales very badly.
We have a time limit of 9 seconds to solve this question. But when the array contains the maximum value of 25,000,000,000,000 then it exceeds that time limit.
20
elements, all equal1000
. Your code will have to analyze one thousand numbers, from1
to1000
, for each item of the input array. So it will repeat the same work twenty times. Can you think of some way to avoid it? \$\endgroup\$