階乘尾部的0(解法思路)
阿新 • • 發佈:2018-01-27
return long 編程題 兩個 body with rail 階乘的計算 temp
昨天看到一個編程題,以為很簡單,結果還費了一番周折才做出來。
題目:設計一個算法,計算出n階乘中尾部零的個數
樣例11! = 39916800,因此應該返回 2
思路: 最無腦的辦法就是直接求出階乘的值,然後統計尾部的0:
1 class Solution { 2 public: 3 /* 4 * @param n: A long integer 5 * @return: An integer, denote the number of trailing zeros in n! 6 */ 7 long long trailingZeros(longlong n) { 8 if(n==0||n==1) 9 {return 0;} 10 11 long long result=1; 12 // write your code here, try to do it without arithmetic operators. 13 for(long long i=1;i<=n;i++) 14 { 15 result = result*i; 16 } 17 int count=0; 18 while(result%10==0) 19 { 20 count++; 21 result = result/10; 22 } 23 return count; 24 } 25 };
這種方法簡單粗暴,但是如果給定n的值很大的話,求階乘的計算量非常大。
下面就有了第二種思路,在乘法計算裏,只要乘以一個10或者10的個位數倍數,結果的後面就會增加一個0。
因為n的階乘中一定會有n/2個偶數,所以我們只需要考慮有多少個5的倍數,結果的末尾就會增加多少個0。
這裏還要考慮到一種情況就是,如果被乘數是5的n次方的倍數話,就結果的末尾增加n個0,例如25可以表示成5*5,一定可以找到一個4的倍數和他相乘使得結果末尾增加兩個0;
那麽到這裏,思路就可以確認為:判斷有多少個被乘數是5的倍數,如果是5的倍數的話,再判斷這個數是不是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) { if(n==0||n==1) {return 0;} int count=0; long long temp = 0; // write your code here, try to do it without arithmetic operators. for(long long i=1;i<=n;i++) { temp = i; while(temp%5==0) { count++; temp = temp/5; } } return count; } };
這樣雖然優化了很多,但是時間復雜度是O(N/5)~=O(N),還是沒有達到O(logN)的要求,
最開始想到我要看從1~n裏有多少個5的倍數,只需要直接用n除以5就可以知道結果了,但是5的倍數裏面還包含了25、125······這些5的多次冪。
如果遇到這些數的話,結果就不是加1而是加2加3····;
但是如果換個思路,我們在統計5的倍數的時候,已經就吧25,125····這些數統計進去了,25的倍數就是比5的倍數能多提供一個0;125的倍數就是能在5的倍數和25的倍數的基礎上再多提供一個0····
依此類推,那我們需要求的結果其實就是
n/5 + n/25 + n/125 + n/625······
代碼實現:
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) { long long count=0; long long a = n/5; while(a>0) { count=count+a; a=a/5; } return count; } };
階乘尾部的0(解法思路)