设计一个算法,计算出n阶乘中尾部零的个数
样例
样例 1:
输入: 11
输出: 2
样例解释:
11! = 39916800, 结尾的0有2个。
样例 2:
输入: 5
输出: 1
样例解释:
5! = 120, 结尾的0有1个。
思想一:碰到这个问题可能首先想到的就是用一个for循环得到n的阶乘,然后在算出末尾有几个零,这种思想只能在n的阶乘在数据类型范围内,才能正确。一旦n的阶乘超过了数据类型的范围后,那么就无法满足,最终无法测试通过。比如n=2356050006340;
在运行过程中就无法得到想要的结果。所以这种方法只能检测一些小数据的阶乘,无法测试大型数据。
思想二:如果深入思考发现每从1开始,每5个数字就能产生末尾0,例如:{1,2,3,4,5,6,7,8,9,10,...},把这些数字抽调出来就变成了一下形式:{...,5,...,10,...15,...20,...25,..},这些数字其实是都能满足
5*k
的数字,是5的倍数。统计一下他们的数量:n1=N/5
。比如如果是101,则101之前应该是5,10,15,20,...,95,100
共101/5=20
个数字满足要求。2、将1中的这些数字化成5*(1、2、3、4、5、...)的形式,内部的1、2、3、4、5、...又满足上面的分析:每5个数字有一个是5的倍数。抽取为:...、25、...、50、...、75、...、100、...、125、...
而这些数字都是25的倍数(5的2次幂的倍数),自然也都满足5*k的要求。
这些数字是25、50、75、100、125、...=5*(5、10、15、20、25、...)=5*5*(1、2、3、4、5、...),内部的1、2、3、4、5、...又满足上面的分析,因此后续的操作重复上述步骤即可。
统计一下第二次中满足条件的数字数量:n2=N/5/5,101/25=(101/5)/5=4。
因为25、50、75、100、125、...它们都满足相乘后产生至少两个0,在第一次5*k分析中已经统计过一次。对于N=101,是20。因此此处的5*5*k只要统计一次4即可,不需要根据25是5的二次幂统计两次。
后面的125,250,...等乘积为1000的可以为结果贡献3个0的数字,只要在5*5*k的基础上再统计一次n3=((N/5)/5)/5即可。
public class Solution { /* * param n: As desciption return: An integer, denote the number of trailing * zeros in n! */ public long trailingZeros(long n) { // write your code here long count = 0; long temp=n/5; while (temp!=0) { count+=temp; temp/=5; } return count; } }