首先基於一個事實:咱們不可能真的把 n! 的結果計算出來,再去數結果的末尾有幾個0;n 很小還好,若是n很大,甚至趨近於無窮大,咱們是不可能這樣作的。緣由主要有二:java
連計算機都算不出來,那咱們怎麼辦呢?別慌,雖然咱們不能直接算出結果,但咱們能夠把問題一步步拆解。算法
首先,咱們想什麼狀況下會產生一個0?code
誒,一個數乘以 10,在末尾就會多出一個 0。而 10 = 5 * 2。class
一組數相乘的結果末尾有幾個0,取決於這組數因式分解後有幾對 5 和 2 的因子。效率
針對於 n! 這個題目,有這樣一個事實:把相乘的數因式分解後,2 的個數確定大於 5 的個數。循環
因此,這個問題能夠拆解爲:只要求出因式分解後有幾個 5 的因子便可,5的個數便是末尾出現的0的個數。計算機
這種解法的思路是:直接將 n! 中的每一個數,按照 5 來因式分解,最後把出現的 5 的個數加起來。時間
public int calculateZeroInFactorial(int n) { int count = 0; // 循環判斷全部的乘數 for (int i = n; i > 0; i++) { if (i % 5 == 0) { // 若是這個乘數能夠對 5 進行因式分解,再看這個乘數能夠分解出幾個5 int a = i; while(a % 5 == 0) { a = a / 5; count++; } } } return count; }
可是這種算法的時間複雜度爲 O(nlog(n)),那有沒有更快的算法呢?while
分析:co
因此,n! 的結果能夠拆分爲多少個 5 因子呢?
n/5 + n/25 + n /125 + n/625 + ….
好比 128!的階乘的結果末尾有幾個0呢?
128/5 +128/25 + 128/125 = 25+5+1 = 31 個
又如:1247! 的階乘的結果末尾有幾個0呢?
1247/5 + 1247/25 + 1247/125 + 1247/625 = 249+49+9+1 = 308 個
public int calculateZeroInLogN(int n) { int count = 0; while (n > 0) { count += n / 5; n /= 5; } return count; }
這種算法的時間複雜度爲 O(log(n)),效率會高不少,並且僅需幾行代碼。