题目:Given an integer n, return the number of trailing zeroes in n!.(Leetcode 172)
C++参考框架:
class Solution { public: int trailingZeroes(int n) { //code } };
1.直接的想法是计算n!后求尾部0的数量,然而随着n增加,n!增长很快,数据存储很成问题,而且时间复杂度为O(n),不能满意,代码也不放了。
2.idea:要计算尾部0的个数,即是计算n!因数中10的个数,即10=2×5的个数。
观察关于关于2和5的因数分解:
1 2 3 4=2×2 5 6=2×3 7 8=2×2×2 9 10=2×5 11 12=2×2×3 13 14=2×7 15=3×5 16=2×2×2×2 . . .
只要是偶数就至少包含一个因数2,个位为0或5的则包含因数5,直观上可以看到1到n所有的分解中因数2比因数5多(我没有严格证明),则问题转化为寻找n!中因数5的个数。n!因式分解中有几个5则尾部就有几个0。
代码如下:
class Solution { public: int trailingZeroes(int n) { int num_of_five=0,t; for(int i=5;i<=n;i+=5) { t=i; while(t%5==0) { ++num_of_five; t/=5; } } return num_of_five; } };
这样就不用计算n!,但是时间复杂度是O((n/5)log5(n/5))=O(nlogn),在n较大时计算时间不能满意。
3.假设现在n=133。
我们只要计算5的数量,则只关注包含因数5的数字,即,5,10,15,20,25,30,...,130共26个数字。
这些数字包含因数5的数量分别为:
1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,2,1,1,1,1,3,1。即
1,1,1,1,(2=1+1),1,1,1,1,(2=1+1),1,1,1,1,(2=1+1),1,1,1,1,(2=1+1),1,1,1,1,(3=1+1+1),1这样一个数列。问题转化为计算有此规律的数列的和,代码如下:
class Solution { public: int trailingZeroes(int n) { int num_of_five=0; while(n>=5) { n/=5; num_of_five+=n; } return num_of_five; } };
时间复杂度为O(logn)。
时间: 2024-11-10 00:18:48