題目
設計一個算法,計算出n階乘中尾部零的個數
樣例
樣例 1:
輸入: 11
輸出: 2
樣例解釋:
11! = 39916800, 結尾的0有2個。
樣例 2:
輸入: 5
輸出: 1
樣例解釋:
5! = 120, 結尾的0有1個。
挑戰
O(logN)的時間複雜度
1.c++/c解法
第一次
想法是通過向十取餘來計算零的個數
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)
{
int t=0,s=1;
for(int i = 1 ;i <= n ; i++)
{
s *= i;
}
while(s%10 == 0)
{
t++;
s /= 10;
}
return t;
}
};
第一次測試數據通過了,但是提交失敗。測試數據達到12階乘以上全部失敗,而且運行時間超時。打算顛倒數字重頭開始計算零的數字
long long trailingZeros(long long n)
{
int t=0,s=1;
int r[150000];
for(int i = 1 ;i <= n ; i++)
{
s *= i;
}
while(s != 0)
{
r[t] = s % 10;
t++;
s /= 10;
}
int len = 0;
for(;r[len]==0;len++)
{
if(r[len]!=0)
break;
}
return len;
}
再一次失敗後覺得是數組長度問題,修改數組長度後還是錯誤。於是覺得是算法問題,不能用數組存放。於是直接每顛倒一位數字便進行判斷:
long long trailingZeros(long long n)
{
int t=0,s=1;
for(int i = 1 ;i <= n ; i++)
{
s *= i;
}
int len=0;
while(s != 0)
{
int r;
r = s % 10;
if(r==0)
{
len++;
}
else break;
t++;
s /= 10;
}
return len;
}
發現這樣的方法還是錯誤,發現是存放階乘結果的s長度不夠。於是修改爲long long int 定義s。結果還是失敗,於是開始反思算法。
修改版算法
可以將每個數拆分成其素因子的乘積,可以發現,0是由2*5產生的,而5的數量一定小於2的數量,因此5的個數決定了結尾0的個數。
只要計算n的階乘中,5這個素因子出現多少次即可。
class Solution {
public:
// param n : description of n
// return: description of return
long long trailingZeros(long long n) {
long long sum = 0;
while (n != 0) {
sum += n / 5;
n /= 5;
}
return sum;
}
};
或者是:
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 numFactor5 = 0;
while (n >= 5)
{
n = n / 5;
numFactor5 += n;
}
return numFactor5;
}
};
python解法
可以將每個數拆分成其素因子的乘積,可以發現,0是由2*5產生的,而5的數量一定小於2的數量,因此5的個數決定了結尾0的個數。
只要計算n的階乘中,5這個素因子出現多少次即可。
class Solution:
# @param n a integer
# @return ans a integer
def trailingZeros(self, n):
sum = 0
while n != 0:
n /= 5#這裏可以替換爲n //= 5(//代表抹除小數部分取整數)
sum+= n
return sum
說實話,這種方法不太會。