Searching & Sorting · 29 of 36
Smallest number with at least n trailing zeroes in factorial
Count the fives hiding inside a factorial to know its trailing zeros, then binary search for the first number with enough of them.
- Simple way
- time O(n log n)
room O(1) - Clever way
- time O(log^2 n)
room O(1)
The problem, simply
The factorial x! is 1 x 2 x 3 x ... x x. For example 5! = 120, which ends in one zero. Given n, find the smallest x such that x! ends in at least n zeros.
The factorial itself is far too big to compute. You need a way to count its zeros without building it.
A story to remember it
Picture it
The fives inside 25!. The multiples of 5 each give one 5, and 25 = 5 x 5 gives two. Total 6, so 25! ends in 6 zeros. 24! has only 4.
- looking now
Examples
One zero
- In
n = 1- Out
5
5! = 120. Smaller factorials have no 5 in them.
Two zeros
- In
n = 2- Out
10
5 and 10 each bring a 5.
A jump
- In
n = 5- Out
25
24! has 4 zeros and 25! has 6. No factorial has exactly 5, so the first one with at least 5 is 25!.
Six zeros
- In
n = 6- Out
25
Same answer: 25 brings two 5s at once.
Way 1: the simple way
Count zeros with the five rule, and try x = 0, 1, 2, ... until the count reaches n.
zeros(x) = x/5 + x/25 + x/125 + ...with whole number division. Each term counts the numbers that bring one more 5.- Start at
x = 0and add 1 untilzeros(x) >= n.
class Solution {
long zeros(long x) {
long count = 0;
for (long p = 5; p <= x; p *= 5) count += x / p; // multiples of 5, 25, 125, ...
return count;
}
public long smallest(long n) {
long x = 0;
while (zeros(x) < n) x++;
return x;
}
}How long it takes: the answer is at most 5n, and each count takes O(log n) steps, so O(n log n). Extra room: O(1).
Way 2: the clever way
zeros(x) never goes down as x grows, so binary search for the first x with zeros(x) >= n.
Two facts make the search small:
zeros(5n) >= n, because5n / 5alone is alreadyn. So the answer is at most5n.- The count only changes at multiples of 5. So the answer is always a multiple of 5. Search over
5 x mformfrom 1 ton.
lo = 1,hi = n. These are multipliers: the real number is5 x m.- Take
mid. Ifzeros(5 x mid) >= n, remember it and try smaller (hi = mid - 1). Otherwise try bigger (lo = mid + 1). - Return
5 x answer.
Binary search over the multiples of 5
01 / 08
We want at least 6 zeros. The answer is a multiple of 5, at most 5 x 6 = 30. So the candidates are 5, 10, ..., 30.
- n
- 6
- done
- answer
- rejected
class Solution {
long zeros(long x) {
long count = 0;
for (long p = 5; p <= x; p *= 5) count += x / p;
return count;
}
public long smallest(long n) {
if (n <= 0) return 0;
long lo = 1, hi = n, answer = n; // the answer is 5 * m for some m in 1..n
while (lo <= hi) {
long mid = lo + (hi - lo) / 2;
if (zeros(5 * mid) >= n) {
answer = mid; // enough zeros: try smaller
hi = mid - 1;
} else {
lo = mid + 1; // too few: go bigger
}
}
return 5 * answer;
}
}How long it takes: O(log n) guesses, each count O(log n), so O(log^2 n). Extra room: O(1).
Watch out for
- Counting 2s instead of 5s. There are always more 2s, so the 5s decide.
- Forgetting the extra 5 from 25, 125, and so on.
x / 5alone undercounts. - Use
long.5 x noverflowsintoncenis above about 400 million. - The plain search over
0..5nalso works. Searching only multiples of 5 just makes the range 5 times smaller.
What interviewers ask next
- Count the trailing zeros of
x!(LeetCode 172). That iszeros(x)alone,O(log x). - How many
xhave exactlyntrailing zeros (LeetCode 793)? The answer is always 0 or 5: find the firstxwith at leastnand the first with at leastn + 1, and subtract. - Trailing zeros of
x!in baseb. Factorbinto primes, count each prime inx!the same way (Legendre's formula), and divide by its power inb. The smallest result wins. - The last nonzero digit of
x!is a much harder follow up, solved by removing pairs of 2 and 5 and tracking the rest modulo 10.
Remember this
Grown-up words: the socks are the prime factors 2 and 5, the five rule is Legendre's formula, "never goes down" means monotonic, and guessing x is binary search on the answer.