- 题目描述
首先分析下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,所以可以推出满足时间复杂度。