首页 > 代码库 > [C++]LeetCode: 88 Factorial Trailing Zeroes (阶乘后导零)

[C++]LeetCode: 88 Factorial Trailing Zeroes (阶乘后导零)

题目:

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

Note: Your solution should be in logarithmic time complexity.

思路:

我们要计算 N! 中有多少个后导0.

我们来找一下规律,考虑n!的质数因子。后缀0,只有可能是质因子2 * 质因子5得到。如果我们可以计算得到min{num(2), num(5)},就可以知道后导0的个数。

举例子:

n = 5! 中包含质因子(2 * 2 *  2 * 3 * 5),包含一个5和三个2. 因而后导0个数为1.

n = 11! 中包含质因子(2^8 * 3^4 * 5^2 * 7) ,包含两个5和三个2.于是后导0个数为2.

我们发现质因子中2的个数总是大于等于5的个数,所以我们只需要计算5的个数就可以了。

如何计算n!的质因子中所有5的个数? 一个简单的办法就是计算floor(n/5)(取整)。但是我们还需要考虑一件事,比如25,,125之类的5的倍数不只含有一个5. 解决办法:先对 n/5, 移除所有单个的5,然后再除以25,移除所有额外的5,以此类推。比如,25中有共有五个5,一个25,先移除单个5,floor(n/5) = 5, 再移除额外的5,floor(n/25) = 1。直到下一个数取0为止。

技术分享

技术分享 如何选取k

Attention:

1. sum需要初始化为0,否则导致未定义行为。

501 / 502 test cases passed.
Status: 

Wrong Answer


Submitted: 31 minutes ago
Input:0
Output:32673
Expected:0

2. 注意内存溢出的问题。 两种办法解决,不断缩小n; 或者改变变量类型。这篇文章有个内存溢出的详细解释。

 i*5一直连乘时出现i = 5^14时,内存溢出(5^13 = 1220703125 < 2^31, but 5^14 = 6103515625 > 2^32)

<span style="font-size:14px;"> for(long long i = 5; n/i > 0; i *= 5)</span>

第十行代码,5^k会导致溢出。无法得到正确答案。一定要避免想当然的套用公式,首先要判断是否都在int的范围内,如果不在,考虑如何避免溢出。

Error Code:

技术分享

复杂度:O(log(n))

AC Code:

<span style="font-size:14px;">class Solution {
public:
    int trailingZeroes(int n) {
        int sum = 0;
        
        for(long long i = 5; n/i > 0; i *= 5)
        {
            sum += n/i;
        }
        return sum;
    }
};</span>

AC Code:

<span style="font-size:14px;">class Solution {
public:
    int trailingZeroes(int n) {
        int sum = 0;
        
        while(n)
        {
            sum += n/5;
            n /= 5;
        }
        return sum;
    }
};</span>




[C++]LeetCode: 88 Factorial Trailing Zeroes (阶乘后导零)