設計一個算法,計算出n階乘中尾部零的個數

  • 題目描述

 

首先分析下n的階乘的規律:

  • 題目分析
階乘 結果
1! 1
2!=1*2 2
3!=1*2*3 6
4!=1*2*3*4 24
5!=1*2*3*4*5 120           (1個0)
6!=1*2*3*4*5*6 720            (1個0)
7!=1*2*3*4*5*6*7 5040          (1個0)
8!=1*2*3*4*5*6**7*8 40320        (1個0)
9!=1*2*3*4*5*6*7*8*9 362880       (1個0)
10!=1*2*3*4*5*6*7*8*9*10 3628800                   (2個0)
11!=1*2*3*4*5*6*7*8*9*10*11 39916800                  (2個0)
          ..............      ............                  (2個0)
15! = 1*2*3*4*5*6*7*8*9*10*11*12*13*14*15 1307674368000   (3個0)
          ............       ............
20!=1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20                                (4個0)
         以此類推       依此類推

故可發現規律:

(1)對於        1、2、3、4、5、6、7、8、9、10、11、12、13、............(&&&&)

可知上述數列,每個隔5個數的階乘後的結果,尾部零的個數會增加一個,即在

5.....10......15......20......25.......30....35......40.......45.......50......55......60......65......70......75.....80.......85.......90......100.........(*****)

這些數字均滿足 5*k 的數字。則在階乘數n之前,利用公式:數量 n1 = n/5,則可知在階乘數n之前,有n1個上述類型的數字。

例如: n = 56

則在56之前應該是5,10,15,20,25,30,35,40,45,50,55,

共56/5=11個數滿足上述數字特徵要求。

(2)將(****)處的特徵數字可以再進行規律尋找,可以化成

    即爲: 5*(1、2、3、4、5、6、7、8、................)

此處可以提一個5出來,說明對應的每個階乘尾部至少都可達到有一個0;

括號中的數字1、2、3、4、5、6、7、8、..............又滿足(1)中的分析過程,對於(&&&&)中的原始數據,可以再次提出5的數字有:

........、25、.......、50、........、75、..........、100、..........、125、...........、150、..........、175、........

即爲:5*5*(1、2、3、4、5、6、7、8、....................)

此處可以提兩個5出來,說明對應的每個階乘尾部至少都可達到有兩個0

括號中的數字1、2、3、4、5、6、7、8、..............又滿足(1)中的分析過程,對於(&&&&)中的原始數據,可以再次提出5的數字有:

......、125、........、250、.......、375、........、500、.......、625、........、750、..........

即爲:5*5*5*(1、2、3、4、5、6、7、8、................)

此處可以提三個5出來,說明對應的每個階乘尾部至少都可達到有三個0;

依次類推:

故可設計程序如下:

//迭代版本
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 num = 0;
        while(n)    
        {
            num += n / 5;   //將符號左邊的值與右邊值相加再賦值給左邊
            n = n / 5;
        }
        return num;
    }
};

代碼分析:

  • 先定義0的個數計數變量num,賦初始值爲0,使用while循環語句,若滿足繼續,不滿足跳出,輸出計數值num。

例1:計算 4! 中尾數0的個數           4!=24

         n=4,進入while循環,執行第一條語句:4 / 5 = 0,故 num = 0 + 4 / 5 =0+0=0 ;執行第二條語句:n = 4 /5 =0

故調出循環,輸出num=0.階乘尾部沒有0.

例2:計算14!中尾數0個數           14!=87178291200

         n=14,進入while循環,執行第一條語句:14 / 5 = 2,故 num = 0 + 14 / 5 =0+2=2;執行第二條語句:n = 14 /5 =2;

        繼續執行while循環,執行第一條語句:2/ 5 = 0,故 num = 0 + 2/ 5 =0+0=0;執行第二條語句:n = 2/5 =0;故調出循環,輸出num=2。階乘尾部有兩個0. 

  • 時間複雜度分析

      題目要求我們時間複雜度爲O(logN),在算法中,每次循環均有除以5的操作,故每次循環數據量縮減爲原來的1/5,所以可以推出滿足時間複雜度。  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章