172. Factorial Trailing Zeroes
Given an integer n, return the number of trailing zeroes in n!.
Example 1:
Input: 3 Output: 0 Explanation: 3! = 6, no trailing zero.
Example 2:
Input: 5 Output: 1 Explanation: 5! = 120, one trailing zero.
Note: Your solution should be in logarithmic time complexity.
结尾数字是0,很快想到,只有末尾出现5和0的时候才可能相乘出0,也就是每出现一次5和0,阶乘的结尾就会多出一个0,先试一把:
public int trailingZeroes(int n) { int result = n / 5; return result; }
果然想的太简单了,在n = 30的时候,期望答案是7,这个算出来是6。想了半天没明白多出来的这个0是怎么乘出来的,于是,决定把阶乘直接算出来,看看是在哪个数比预想的多出现了一个0。动手之后才发现,阶乘的算出的值过大,大概在17!以后就已经超出了java中long能表示的最大值。印象里还有个BigInteger可以用,简单看了下接口后,得到如下测试代码:
public static int trailingZeroes(int n) { BigInteger sum = BigInteger.valueOf(1); for (int i = 1; i <= n; i++) { sum = sum.multiply(BigInteger.valueOf(i)); } int num = 0; char[] arr = sum.toString().toCharArray(); int len = arr.length - 1; while (arr[len--] == '0') { num++; } return num; } public static void main(String[] args) throws IOException { Scanner sc = new Scanner(System.in); System.out.println("please enter the number!"); int num = sc.nextInt(); for (int i = 0; i <= num; i++) { System.out.println(i + ": " + trailingZeroes(i)); } }
输入n = 30,发现在25的时候输出值一次加2。
反应过来在5的幂次方的情况下,结尾也会增加0,piapia一通敲,自信提交:
public static int trailingZeroes(int n) { int sum = 0; long m = 5; while (n >= m) { sum += n / m; m *= 5; } return sum; }
这回对倒是对了,但是运行时间比其他答案多了一个数量级,WTF!!!
leetcode中排名比较靠前的答案解法大致如下:
public static int trailingZeroes4(int n) { int ans = 0; while (n != 0) { ans += n / 5; n /= 5; } return ans; } public static int trailingZeroes5(int n) { return n == 0 ? 0 : n / 5 + trailingZeroes5(n / 5); }
本质上都是n!中,最多能分解出几个5相乘,这也更好的解释了为什么30!在乘到25时为什么结尾一下子多了2个0,因为25 = 5 * 5。自己的后一次提交,虽然答案对了,但是还是没有看出问题的本质,循环中一直在做大位数除法(n/m , 测试用例中n取值很大),所以运行时间会长很多。