2. 尾部的零

设计一个算法,计算出n阶乘中尾部零的个数
样例
11! = 39916800,因此应该返回 2.
这其实是一个数学题,思路倒是很简单,主要就是找每个数有多少个5的因子(只要有5的因子,因为是阶乘,就能保证有数和5匹配乘之后是0(有大量的2,4,6,8))。只有一个5的因子的数好说,只要找到一个这样的数,计数器加1就行了,但是像25,75,100这样有两个5的因子的数,还有像3125这样有四个5的因子的数怎么处理才是难点所在,很容易想到的一个方法是遍历所有能被5整除的数,起始为5,每次加5,然后判断这个数可以被5整除多少次,这样的时间复杂度是很高的,数越大时间复杂度越高,不出意外超出了时间限制,数比较小的话还是可以用这种方法的:

long long trailingZeros(long long n) {
        
        long long  res=0;
        if(n<5)
        return 0;
        
        for(int i=5;i<=n;i=i+5)
        {
            int j=i;
            while(j%5==0)
            {
                res++;
                j/=5;
            }
        }
        return res;
        // write your code here, try to do it without arithmetic operators.
    }

百度了下找到另外一种解法:是这么来的,就一直除以5,上面说了,我们主要要找到有多少个5,就是这个数可以分解成多少个5来,那么一直除就可以了,比如105,里包含了多少5,105/5=21,共有21个5,这是末尾是5或0的数目,21里还有4个5,21/5=4,这是有两个因式5的数目(不是很理解),4里面就没有5了,这样算下来应该是所以应该是21+4=25个0,以此类推:

在振哥的指导下理解了这种思路了,其实还是自己懒得在纸上画一下,画一下应该也能发现这样的规律,以105阶乘为例:
105=(1,2,3,4,5,6...105)
=5^21(1,2,3,4,5....21,.... 1,2,3,4,6,7,8,9...)
=5^21 * 5^4(1,2,3,4.....)
省略号之前的都是除以5之后还能连续起来的,后面的就不再有5整倍数了,这样看来这实际上是一个递归了。

  long long trailingZeros(long long n) 
     {
         long long res=0;
        
         while(n/5>0)
         {
             res+=(n/5);
             n/=5;
         }
         return res;
     }

over

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容