【原创】leetCodeOj --- Factorial Trailing Zeroes 解题报告

原题地址:

https://oj.leetcode.com/problems/factorial-trailing-zeroes/

 

 

题目内容:

Given an integer n, return the number of trailing zeroes in n!.

Note: Your solution should be in logarithmic time complexity.

 

方法:

数学原理很简单,稍微讲一下

我们知道,一堆数相乘出了0,除了有0之外,需要一个2,5数对。比如4 × 5,可以分解为2 × 2 × 5,有一个2,5数对,所以有1个0。推而广之,一堆数连乘,能因式分解出几个2,5数对就有几个0。

 

由于在阶乘中,分解出的2肯定比5多,(要证明吗?稍微证一下。。2的倍数,也就是全体偶数在一组阶乘中肯定比5的倍数多,而只有2和5的倍数能因式分解出2,5数对来组合,因此,每一个2,5数对和数字5一一对应),因此,实际上给了我们n,我们需要找出,从1到n这个区间中,能分解出几个5。

 

数学原理讲完了,讲算法。

先想想,我们如何求1到n的所有5的倍数?答案很简单,n/5就可以了,因为每5个数就会有一个5的倍数。我们先把所有5的倍数个数加到结果中先。

可是这样还远远不够,因为25中能分解出2个5,而所有25的倍数都能分解出两个5,以此类推。

但我们离答案已经很近了。n/25是区间内所有25的倍数,由于25的倍数在第一轮5的倍数中,已经加了一个5,因此,这一轮也只需要加一次就行了。加上所有25的倍数的个数到结果中去,以此类推。

 

最后需要注意一点:乘法溢出问题。5的13次方是末尾,14次方就溢出了。

 

具体代码:

Python就三行,我去

class Solution:
    # @return an integer
    def trailingZeroes(self, n):
        l = [5 ** i for i in range(1,14)]
        q = [n / key for key in l]
        return sum(q)

 

C++有点多

class Solution {
private:
    vector<int> dict;
public:
    Solution () {
        int start  = 5;
        int border = 13; 
        for (int i = 0; i < 13; i ++) {
            dict.push_back(start);
            start *= 5;
        }
    }
    
    int trailingZeroes(int n) {
        int res = 0,i = 0;
        int p;
        while (i < dict.size() && (p = n / dict[i ++]) > 0) {
            res += p;
        }
        return res;
    }
};

 

复杂度的要求毫无疑问是满足的,常数次,比log都好。

posted on 2015-01-19 23:46  shadowmydx'sLab  阅读(243)  评论(0编辑  收藏  举报

导航