一、問題描述:在lintcode上有這麼一個問題,如下圖所示。設計一個算法,計算出n階乘中尾部零的個數。
二、嘗試
(1)相信很多人看到這個問題的第一個想法就是,先計算n階乘的結果,然後對10進行求餘判斷,而被10整除的次數就是尾部零的個數。代碼如下:
long long trailingZeros(long long n) {
// write your code here, try to do it without arithmetic operators.
//計算n階乘
int s=1;
for(int i=1;i<=n;i++)
{
s=s*i;
}
//對結果進行判斷
int num = 0;
//對10進行求餘
while(s%10==0)
{
num++;
s = s/10;
}
return num;
}
看結果,說容易陷入死循環。爲什麼會陷入死循環呢?n纔是105哎,105!等於多少?用了一個在線階乘計算器計算髮現結果很大1.0813967582402912e+168。而int是32位,數據早已溢出,所以,用於存放階乘結果的s要改成長整型long long int。
(2)再次嘗試,發現依然運行超時。看來計算n階乘佔用的空間和時間都比較長。
(3)當我們嘗試從1到n逐次計算n階乘時,會發現一個規律,遇見能被5整除的數時,尾部0就可+1;而尾部的0一共有多少個,就要看這個數包含多少個5的因子。比如1到4的階乘結果分別爲1、2、6、24,5到9的階乘結果是120、720、5040、40320、362880,10到14的結果分別是3628800、39916800、479001600、6227020800、87178291200,然後15!=1307674368000。也就是5有一個0,10有2個0,15有3個0,20有4個0,25有6個0,30有7個0等等,代碼如下
long long trailingZeros(long long n) {
// write your code here, try to do it without arithmetic operators.
//計算n階乘
long long num = 0;
long long temp=n;
while(temp)
{
temp /= 5;
num += temp;
}
return num;
}
結果
值得注意的一件事就是,其中數據類型的定義,要是long long類型的,這一點題目在定義的時候函數結果上也有提示。
在線計算階乘的地址http://www.99cankao.com/statistics/factorial-calculator.php