I’m solving LeetCode #172:
Given an integer n, return the number of trailing zeroes in n!
Constraints:
0 <= n <= 104
My code finds the answer of n! first and then counts the number of trailing zeroes. However, running the code throws a stack overflow exception, and I can’t for the life of me figure out why.
This is the code:
class Solution {
public int trailingZeroes(int n){
int fact = findFactorial(n); // 120
int ans = 0;
// how many zeroes does fact have?
String ansString = Integer.toString(fact);
// edge - if string is only one character long
if (ansString.length()==1) {
return 0;
}
// loop from the end counting the continuous zeroes
for (int i= ansString.length()-1 ; i > 0; i--){
Character cha = ansString.charAt(i);
if (cha.equals('0')) {
ans++;
}
else {
break;
}
}
return ans;
}
public int findFactorial(int n){
// base case
if (n==1) return 1;
// reduct towards base case
else {
int f = n * findFactorial(n-1);
return f;
}
}
}
Advertisement
Answer
You said:
Given an integer n, return the number of trailing zeroes in n!
Constraints:
- 0 <= n <= 104
First, your solution won’t work because an int can’t hold that large a number.
You need to use BigInteger as shown below.
The following recursive form will compute 104! without much noticeable delay.
public static BigInteger factorial(int n) {
if (n == 1 || n == 0) {
return BigInteger.ONE;
}
return factorial(n-1).multiply(BigInteger.valueOf(n));
}
String fact = factorial(1000).toString();
System.out.println(fact.replaceAll("\d+?(0*)$", "$1").length());
prints
249
But you don’t need to compute the factorial to solve the actual problem. Consider the following.
The product of all the numbers from 1 to N must have divisors of 10 (i.e. 2 and 5). 5 will occur the least number of times so that is where you need to focus. The number of trailing zeros is equal to the number of times that 10 divides N. And since 5 may divide a given term more than once (e.g. 25, and 125) you need to update the divisor as well.
int n = 1000; // factorial candidate
int sum = 0;
int k;
for (int d = 5; (k = n/d) > 0; d*=5) {
sum += k;
}
System.out.printf("%d! has %d trailing zeros", n, sum);
prints
1000! has 249 trailing zeros
And here is the recursive solution (although not as efficient).
public static int trailingZeros (int n) {
if (n > 0) {
return trailingZeros(n/5) + n/5;
}
return 0;
}