• 【LeetCode】Factorial Trailing Zeroes


    Factorial Trailing Zeroes:

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

    Note: Your solution should be in logarithmic time complexity.

     


    Solution:

    对n!做质因数分解n!=2x*3y*5z*...

    显然0的个数等于min(x,z),并且min(x,z)==z

    证明:

    对于阶乘而言,也就是1*2*3*...*n
    [n/k]代表1~n中能被k整除的个数
    那么很显然
    [n/2] > [n/5] (左边是逢2增1,右边是逢5增1)
    [n/2^2] > [n/5^2](左边是逢4增1,右边是逢25增1)
    ……
    [n/2^p] > [n/5^p](左边是逢2^p增1,右边是逢5^p增1)
    随着幂次p的上升,出现2^p的概率会远大于出现5^p的概率。
    因此左边的加和一定大于右边的加和,也就是n!质因数分解中,2的次幂一定大于5的次幂

    所以,自然想到解法一:从1到n中提取所有的因子5,效率是 O(log1+log2+log3+……+logn) = O(logn!)。

    解法二:

    由上述分析可以继续发现,起作用的只有在1..n中能被5整除的那些数。而对于每一个n而言,在1..n中这样的数有 [n/5] 个。将这 [n/5] 个数从 1..n 中提出来,从小到大排成一个数列,也就是 5, 10, 15 ...  [n/5]*5。现在将这个数列所有数统一除以5(因为这个数列的长度是[n/5],而每个数都剔除一个因子5,所以计数器得到[n/5]个因子5),此时数列变成 1, 2, 3 ... , [n/5],此时问题又转化为 1..[n/5] 的平凡子问题,此时有可以将所有能被5整除的数提取出来,然后又统一剔除一个因子5,再转化为规模更小的平凡子问题……直到 [n/5]==0 问题终止。

    所以对于每个阶段而言,对于 1..n,都可以统一剔除得到 [n/5] 个因子,最后递推可得解。

    总结与升华:

    实际上,相对于解法一,解法二的改进在于,对于 1..n 统计因子5的时候,把握住了连续的第 5^(c-1) 到 5^(c)-1 位置上的数,能被5整除的数它们的因子5的个数都是相同的的特点,也就是 1..4 因子5个数都是0个,5..24 因子5的个数是 1 个,25..124 因子5的个数都是 2 个…………所以一次性可以跨越一大段数来统计,而且随着 c 增大,一次跨越的数的个数越来越多,这也就是 log 函数的特点,随着 x 增大,函数增长的越来越慢,这也是 log 算法共同的特性。

    代码如下:O(logn)

    1 class Solution:
    2     # @param {integer} n
    3     # @return {integer}
    4     def trailingZeroes(self, n):
    5         ans = 0
    6         while n > 0:
    7             ans += n/5
    8             n /= 5
    9         return ans

     Reference:http://www.cnblogs.com/ganganloveu/p/4193373.html

     

  • 相关阅读:
    第五周作业
    第四周作业
    第三周作业
    第二周作业
    第一周作业
    FileZilla连接centos7失败处理(SSH)
    单例设计模式
    JQuery中的$符号的作用----网摘
    浅谈关于“中文编程”是否会成为中国程序员的一颗“银弹”
    第8周作业 邱鹏 2013551628
  • 原文地址:https://www.cnblogs.com/maples7/p/4474483.html
Copyright © 2020-2023  润新知