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

  • 题目描述

首先分析下n的阶乘的规律:

  • 题目分析
阶乘 结果
1! 1
2!=1*2 2
3!=1*2*3 6
4!=1*2*3*4 24
5!=1*2*3*4*5 120           (1个0)
6!=1*2*3*4*5*6 720            (1个0)
7!=1*2*3*4*5*6*7 5040          (1个0)
8!=1*2*3*4*5*6**7*8 40320        (1个0)
9!=1*2*3*4*5*6*7*8*9 362880       (1个0)
10!=1*2*3*4*5*6*7*8*9*10 3628800                   (2个0)
11!=1*2*3*4*5*6*7*8*9*10*11 39916800                  (2个0)
          ..............      ............                  (2个0)
15! = 1*2*3*4*5*6*7*8*9*10*11*12*13*14*15 1307674368000   (3个0)
          ............       ............
20!=1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20                                (4个0)
         以此类推       依此类推

故可发现规律:

(1)对于        1、2、3、4、5、6、7、8、9、10、11、12、13、............(&&&&)

可知上述数列,每个隔5个数的阶乘后的结果,尾部零的个数会增加一个,即在

5.....10......15......20......25.......30....35......40.......45.......50......55......60......65......70......75.....80.......85.......90......100.........(*****)

这些数字均满足 5*k 的数字。则在阶乘数n之前,利用公式:数量 n1 = n/5,则可知在阶乘数n之前,有n1个上述类型的数字。

例如: n = 56

则在56之前应该是5,10,15,20,25,30,35,40,45,50,55,

共56/5=11个数满足上述数字特征要求。

(2)将(****)处的特征数字可以再进行规律寻找,可以化成

    即为: 5*(1、2、3、4、5、6、7、8、................)

此处可以提一个5出来,说明对应的每个阶乘尾部至少都可达到有一个0;

括号中的数字1、2、3、4、5、6、7、8、..............又满足(1)中的分析过程,对于(&&&&)中的原始数据,可以再次提出5的数字有:

........、25、.......、50、........、75、..........、100、..........、125、...........、150、..........、175、........

即为:5*5*(1、2、3、4、5、6、7、8、....................)

此处可以提两个5出来,说明对应的每个阶乘尾部至少都可达到有两个0

括号中的数字1、2、3、4、5、6、7、8、..............又满足(1)中的分析过程,对于(&&&&)中的原始数据,可以再次提出5的数字有:

......、125、........、250、.......、375、........、500、.......、625、........、750、..........

即为:5*5*5*(1、2、3、4、5、6、7、8、................)

此处可以提三个5出来,说明对应的每个阶乘尾部至少都可达到有三个0;

依次类推:

故可设计程序如下:

//迭代版本
class Solution {
public:
    /*
     * @param n: A long integer
     * @return: An integer, denote the number of trailing zeros in n!
     */
    long long trailingZeros(long long n) {
        // write your code here, try to do it without arithmetic operators.
        long long num = 0;
        while(n)    
        {
            num += n / 5;   //将符号左边的值与右边值相加再赋值给左边
            n = n / 5;
        }
        return num;
    }
};

代码分析:

  • 先定义0的个数计数变量num,赋初始值为0,使用while循环语句,若满足继续,不满足跳出,输出计数值num。

例1:计算 4! 中尾数0的个数           4!=24

         n=4,进入while循环,执行第一条语句:4 / 5 = 0,故 num = 0 + 4 / 5 =0+0=0 ;执行第二条语句:n = 4 /5 =0

故调出循环,输出num=0.阶乘尾部没有0.

例2:计算14!中尾数0个数           14!=87178291200

         n=14,进入while循环,执行第一条语句:14 / 5 = 2,故 num = 0 + 14 / 5 =0+2=2;执行第二条语句:n = 14 /5 =2;

        继续执行while循环,执行第一条语句:2/ 5 = 0,故 num = 0 + 2/ 5 =0+0=0;执行第二条语句:n = 2/5 =0;故调出循环,输出num=2。阶乘尾部有两个0. 

  • 时间复杂度分析

      题目要求我们时间复杂度为O(logN),在算法中,每次循环均有除以5的操作,故每次循环数据量缩减为原来的1/5,所以可以推出满足时间复杂度。  

猜你喜欢

转载自blog.csdn.net/gaoyu1253401563/article/details/82414580
今日推荐