計算階乘之後的零個數

寫在前面

覺得寫得好,有所收穫,記得點個關注和點個贊,不勝感激。
我覺得吧,以後像這種純粹就是進行數學分析的問題,我就要把它記錄下來,這種問題給你時間讓你去分析,可能就能分析出來,但是限定你時間讓你解決,很容易卡住,所以遇到了就學習思路,然後以後如果碰到類似的問題,那麼解決起來就非常迅速利落了。

問題描述

在這裏插入圖片描述

問題解決

首先肯定不能依賴於把階乘算出來再去判斷有多少個零了,因爲階乘很容易就溢出了,所以先一步一步理一下思路吧。首先末尾有多少個 0 ,只需要給當前數乘以一個 10 就可以加一個 0

再具體對於 5!,也就是 5 * 4 * 3 * 2 * 1 = 120,我們發現結果會有一個 0,原因就是 2 和 5 相乘構成了一個 10。而對於 10 的話,其實也只有 2 * 5 可以構成,所以我們只需要找有多少對 2/5。我們把每個乘數再稍微分解下,看一個例子。

11! = 11 * 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 
= 
11 * (2 * 5) * 9 * (4 * 2) * 7 * (3 * 2) * (1 * 5) * (2 * 2) * 3 * (1 * 2) * 1

對於含有 2 的因子的話是 1 * 2, 2 * 2, 3 * 2, 4 * 2 ...。對於含有 5 的因子的話是 1 * 5, 2 * 5...。含有 2 的因子每兩個出現一次,含有 5 的因子每 5 個出現一次,所有 2 出現的個數遠遠多於 5,換言之找到一個 5,一定能找到一個 2 與之配對。所以我們只需要找有多少個 5。直接的,我們只需要判斷每個累乘的數有多少個 5 的因子即可。

public int trailingZeroes(int n) {
    int count = 0;
    for (int i = 1; i <= n; i++) {
        int N = i;
        while (N > 0) {
            if (N % 5 == 0) {
                count++;
                N /= 5;
            } else {
                break;
            }
        }
    }
    return count;
}

不過上面的思路並不是最優的思路,我們還可以進一步的優化一下。對於一個數的階乘,就如之前分析的,5 的因子一定是每隔 5 個數出現一次,也就是n! = 1 * 2 * 3 * 4 * (1 * 5) * ... * (2 * 5) * ... * (3 * 5) *... * n。因爲每隔 5 個數出現一個 5,所以計算出現了多少個 5,我們只需要用 n/5 就可以算出來。

但還沒有結束,繼續分析。... * (1 * 5) * ... * (1 * 5 * 5) * ... * (2 * 5 * 5) * ... * (3 * 5 * 5) * ... * n。每隔 25 個數字,出現的是兩個 5,所以除了每隔 5 個數算作一個 5,每隔 25 個數,還需要多算一個 5。也就是我們需要再加上 n / 25 個 5

同理我們還會發現每隔 5 * 5 * 5 = 125 個數字,會出現 3 個 5,所以我們還需要再加上 n / 125 。綜上,規律就是每隔 5 個數,出現一個 5,每隔 25 個數,出現 25,每隔 125 個數,出現 3 個 5... 以此類推。最終 5 的個數就是 n / 5 + n / 25 + n / 125 ...。寫程序的話,如果直接按照上邊的式子計算,分母可能會造成溢出。所以算 n / 25 的時候,我們先把 n 更新,n = n / 5,然後再計算 n / 5 即可。後邊的同理。

public int trailingZeroes(int n) {
    int count = 0;
    while (n > 0) {
        count += n / 5;
        n = n / 5;
    }
    return count;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章