版权声明:转载请联系博主 https://blog.csdn.net/Watkins_OS/article/details/83244384
1. 题目描述
给定一个整数n,返回n!结果尾数中零的数量。
说明:
你算法的时间复杂度应为O(log n)
示例1:
输入:3 输出:0 解释:3! = 6,尾数中没有零。 |
示例2:
输入:5 输出:1 解释:5! = 120,尾数中有1个零。 |
2. 朴素法求解
顾名思义,可以先求出阶乘,再利用对10的求余来作为次数累加的循环条件。但是时间复杂度不符合要求,经测试,为“时间超时”。
class Solution(object):
def trailingZeroes(self, n):
"""
:type n: int
:rtype: int
"""
fact = 1
for i in range(2, n+1):
fact *= i
rcnt = 0
while fact%10 == 0:
rcnt += 1
fact //= 10
return rcnt
3. 进一步优化
要使得尾数为0,其中必然会有5的倍数的存在。每逢一个5的出现,前面就会有偶数的存在,所以不需要考虑偶数的因素。数字递增的过程中会发现,凡5的累积倍数均生成数个0,比如25,可以拆分成两个5。这里,直接对n逢五递增,并对每一个5的倍数进行拆分,而且累加次数。经测试,显示“内存不足”。
class Solution(object):
def trailingZeroes(self, n):
"""
:type n: int
:rtype: int
"""
rcnt = 0
for i in range(5, n+1, 5):
cur = i
while cur%5 == 0:
rcnt += 1
cur //= 5
return rcnt
原因在于,range所产生的列表,在遇到百万级的数字时会超出其限制大小。所以考虑将for循环改写成while循环避免这种情况。经测试,显示“时间超时”。
class Solution(object):
def trailingZeroes(self, n):
"""
:type n: int
:rtype: int
"""
rcnt = 0
while n >= 5:
cur = 5 * (n/5)
while cur%5 == 0:
rcnt += 1
cur //= 5
n -= 5
return rcnt
4. 分析规律
要在不大于n的范围内寻找5的简单倍数以及5的累计倍数次数,可以分解成两个部分。第一部分,5的简单倍数,可以直接整除5就可以得到;第二部分,5的累计倍数次数,可采用前面的除值的结果除以5,依次递归下去,直到为0。比如:75除以5得15,即存在15个5的简单倍数,再利用15除以5得3,即3个5的累计倍数次数为2的值,分别是25、50、75。经测试,显示“通过”。
class Solution(object):
def trailingZeroes(self, n):
"""
:type n: int
:rtype: int
"""
rcnt = 0
while n > 0:
n //= 5
rcnt += n
return rcnt
其递归格式为:
class Solution(object):
def trailingZeroes(self, n):
"""
:type n: int
:rtype: int
"""
if n == 0:
return 0
else:
return (n//5) + self.trailingZeroes(n//5)