算法题:尾部的零


题目描述:

设计一个算法,计算出n阶乘中尾部零的个数

样例

11! = 39916800,因此应该返回 2



思路:

      刚开始我就想到最笨的方法,就是先把阶乘的数求出来,在不断循环进行求余操作。可是我却忽略了一点就是,计算机没用那么单位能够储存100多的阶乘之后的数目,所以此方法不同。算法如下:

算法1,时间复杂度最复杂,但是最简单的方法,只适合小数目阶乘        
         int top = 1;
         while (n!=0) {
             top*=n--;
         }
        
         long numb = 0;
         while ( true ) {
             int temp = top/10;
             int leave = top-temp*10;
             if (leave==0){
                 numb++;
             }else{
                break;
             }
            top/=10;
         }
        
         return numb;

之后百度找到了其他两个较好的算法,算法2的时间复杂度为O(n),算法3的时间复杂度为O(log n)

算法2:

        long count = 0;
        long pwr = 25;
        for (long temp = 5; temp<=n;temp+=5) {
            // for 循环内部的temp 是5的倍数,因此首先进行+1操作
            count++;
            pwr = 25;
            // 判断是不是25、125、625...倍数,并根据每次Pwr的变化进行+1操作
            while(temp % pwr == 0 ) {
                count++;
                pwr *= 5;
            }
        }
        return count;


算法3:

思路:

这些数字是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/5101/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即可。

          long count = 0;
        long temp = n/5;
        while (temp!=0) {
            count+=temp;
            temp/=5;
        }
        return count;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值