今天在领扣看到了一个算法题,题目是这样的:
乍一看感觉还是蛮简单的,但是实际操作起来却没那么容易,也看了网上有关这道题的解释,几乎没有能彻底说明白的。经过我的研究终于搞清楚了所以就想给大家带来一篇真正能够让大家浅显易懂的解释。按照我们正常的思路(也许只是我的思路,估计你们会有更好的,嘻嘻),显示算出阶乘的结果,然后再将结果分割成数组,从后遍历直到不是0为止。最后统计一下遍历出0的个数就搞定了。但是我们做题还是想做完整一点(起码有强迫症的我是这样的,嘿嘿)题目挑战要求我们需要实现O(logN)的时间复杂度。如果按照我们之前的思路肯定要用到循环遍历,如果这样就肯定不是O(logN)的时间复杂度了。
有些童鞋可能要问到什么是时间复杂度?本来是想给大家详细解说一番的,单本文章主要讨论的这道算法题的解法。希望小伙伴们在看本文章前先去查阅一下有关时间复杂度的概念,这样会对本文章的理解会更深的哦!
我们言归正传,题目说要计算N阶乘尾部0的个数。那么有些小伙伴就要问了:“既然你说用循环不符合要求,那我我们怎么去算阶乘呢?”。但是你有没有想到做这道题根本不用去计算阶乘呢?这就需要我们研究数字末尾的0到底是如何产生的。
举个例子来说:1200=12*10*10,也就是说1200尾部的0是由两个10产生的,那么10又是由谁产生的呢?
10=2*5
可以说10是由2和5产生的,但是我们继续看:
20=2*2*5;30=2*3*5;40=2*2*2*5······
可以发现随着10位数越大里面2增加越多,而5增加的却很慢。所以我们可以大致的理解为10是由5产生的。
一个数字后面有几个0那么它的因数就有几个10(这个不用我再啰嗦了,大家自行领会)
那我们再说阶乘,先拿75的阶乘来说吧:
75!=1*2*3*4*5*6*7*8*9*10*...*75
想知道结果末尾有几个0,首先得知道从1乘到105一个产生了几个10,上面我们说的10是由5产生的(5*一个偶数),那么从以1开始每5个数就会至少产生一个10,如下图所示:
我们从1-75中筛选出了能够产生10的15个数字(它们都是5的倍数都包含了5)
按照以上方法每5个数又会产生一个5来进行第二次筛选,我们可以从中看到25,50,75是可以产生两个5的 ,也就说能产生两个10,如图:
我们又从中筛选了出了3个数字(说白了这三个数字就是能够产生两个5的另一个5,第一个5在第一次筛选就已经刨去了),到现在为止,所有的5我们已经全部找出,第一次筛选的15个加上第二次的3个,一共18个,也就是说75的阶乘末尾有18个0.
按照以上的方法,我们大致就有了一个思路了,给定一个数的阶乘,用这个数不断地除以5,直到结果为0为止。把每次得数相加就是最终的
结果(如果在除的过程中产生余数,将余数忽略,只取整数部分)。
本人是搞前端开发的,所以用JS实现了这个功能,如图:
大家如果有问题可以私信我,发现文章中出现的问题也可以提出来。写这么多也难免会出现错误,嘿嘿嘿。