阶乘尾部的0(解法思路)

昨天看到一个编程题,以为很简单,结果还费了一番周折才做出来。

 

题目:设计一个算法,计算出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(long long 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;
    }
};

 

 

 

 

 

posted @ 2018-01-27 00:25  鼎雲  阅读(530)  评论(0编辑  收藏  举报