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; }