問題描述:設計乙個演算法,計算出n階乘中尾部零的個數。
樣例:11!
=3991680011!
=39916800
,因此應該返回 2。
解答(js實現):
const trailingzeros = function
(n)
return sum;
}
分析:思考乙個數尾部的零是怎麼得來的,乘以10對吧,所以n的階乘尾部有多少零就可以看成它有多少個10這個因子,而10又可分解為兩個質因數相乘 2×
5 2×5
。將 n!
n
!分解為質因數相乘的形式,大概是這樣: n!
=1×2
×3×(
2×2)
×5×(
2×3)
×7×(
2×2×
2)×(
3×3)
×(2×
5)..
. n!=
1×2×
3×(2
×2)×
5×(2
×3)×
7×(2
×2×2
)×(3
×3)×
(2×5
)...
顯然,2的個數會比5的個數多,所以有多少個5就會有多少個10。故而問題就轉化為尋找 n!
n
!的結果有多少個5這個因子。
那麼這個怎麼找呢?我們看一下上邊的等式,現在已經乘到10了,出現了2個5,想象一下繼續乘下去的情況,到15時會再出現乙個,到20時又會再出現乙個,到25時則會出現2個,繼續看下去,就會發現乙個規律:
(1) 每逢遇到5的倍數,就會出現乙個;
(2) 每逢遇到5的冪次方的倍數,就會出現5的冪次方的指數個,為了便於計算,我們把遇到5的冪次方的倍數時也算到5的倍數裡,這時遇到5的冪次方的倍數就會出現(5
的冪次方
的指數−
(5的冪
次方的指
數−1)
) (5的冪
次方的指
數−(5
的冪次方
的指數−
1)
)個,也就是1個。
這樣用文字來說會有點繞,我們不妨用代數式說明一下:
根據以上,我們不難得出乙個公式: su
m=n5
+n52
+n53
+n54
+⋅⋅⋅
s um
=n5+
n52+
n53+
n54+
··
·有了這個公式,問題就容易了,只需求出
log5
n log5
n,取整,然後將其作為迴圈次數累加就行了。
js中有math.log()函式,返回乙個數的自然對數(loge, 即ln)。雖然沒有直接求
log5
n log5
n的方法,但
log5n=
lnnln5
log5n
=lnn
ln
5,所以n(包括n)以內5的冪次方的最大指數可求得:
var power = math.floor(math.log(n) / math.log(5));
至此,我們從1開始迴圈到power,每次迴圈都加上公式中對應迴圈次數的項,即可得到結果:
var sum = 0;
for (var i=1;i<=power;i++)
總結:由以上的計算方式可以看出,power就是 lnnln
n,所以符合o(logn)的時間複雜度。在做這道題時,也找了不少資料,很多都提到求sum的那個公式,但是具體怎麼來的都沒有很清晰地寫思路,於是自己就試了試,期間也跑偏了幾次,還好最後自圓其說地歸納出來了,希望對看到的朋友有所幫助。
另外,還有一種思路也能按o(logn)的時間複雜度實現,這篇部落格對於另一種思路寫得很清晰,博主很用心,推薦一下 ^-^ 。
2 尾部的零
問題描述 設計乙個演算法,計算出n階乘中尾部零的個數 樣例11 39916800 因此應該返回 2.這個問題相信很多老鐵都已經遇到過了,很經典的乙個題目,還是那句老話,重要的是考慮的過程,是如何想到以5的個數來統計0的個數呢?又是如何想到除以25 除以125.的呢?這些事重點。首先n 中,哪些數字相...
2 尾部的零
描述 設計乙個演算法,計算出n階乘中尾部零的個數。樣例 11 39916800,因此應該返回 2 挑戰 o logn 的時間複雜度 分析 假如你把1 2 4 n中每乙個因數分解質因數,結果就像 1 2 3 2 2 5 2 3 7 2 2 2 10進製數結尾的每乙個0都表示有乙個因數10存在 任何進製...
2 尾部的零
剛看到這道題時沒多考慮,就是利用階乘算出結果然後轉為字元陣列,判斷零的個數 剛發現判斷的地方寫錯了 但是如果輸入的值非常大,超過了取值範圍,就會報錯,而且這道題的思路不是這樣的 我是個沒有腦子的人!思路 乘積中出現0一定是2和5的乘積具體思路就不寫了,別人都寫好了 public class seco...