一.问题描述
Given an integer n, return the number of trailing zeroes in n!.
Example 1:
Input: 3 Output: 0 Explanation: 3! = 6, no trailing zero.
Example 2:
Input: 5 Output: 1 Explanation: 5! = 120, one trailing zero.
Note: Your solution should be in logarithmic time complexity.
二.解题思路
一开始没看清Note要求时间复杂度O(logN)
上手就是一个就阶乘的递归然后算末尾0个数,最后当然成功TLE(超时).
回过神来发现note,然后才仔细思考这道题。
需要回归题目,思考一下末尾0是怎么来的:不管是直接乘10,还是25*4,125*8这种,其实每个0我们都是可以转化成5*2。
相当于有多少末尾0完全取决于有多少5和2对。
在1*2*3...*n!.想象一下把n!中所有i都因式分解,尽可能分解出5出来,比如10分解成5*2, 25分解成5*5。
2很容易拿到,比如说2,4,8都可以分解出2出来,所以这道题最后0的数量取决于n!中能分解出来的5的因子的个数,
同时我们得保证不能直接算n!,得保持logN复杂度。
要计算5的因子数量,提供两种思路:
1.求和n/5^i (从i=1到i,直到5^(i+1)>n)。
我们知道我们就是要算n!中能分解出多少5出来
step1:首先计算从1~n有多少个数至少能因式分解出一个5的出来(即能被5整除的数),那就是让n/5。
step2:然后计算有多少个数能至少因式分解出2个5出来,得让结果加上这部分数量(可能有些人说能分解出2个5不是应该加两倍吗,但是要知道我们是在处理完step1的情况下处理的step2,能分解出2个5的肯定能分解出1个5,因为已经在step1加了一倍了,下同理),那就是n/5^2.
step:...:一直持续的step i
2.求和n/5 (注意n的更新,n=n//5,直到n小于5为止)
方法1是一个自下而上,就是从5~5^i。既然如此,我们直接让n=n/5,这样子相当于让每个能整除5的数都整除掉1个5。
由方法一step1我们知道n/5表示有n/5个数至少能分解出1个5,那么我们让结果加上n/5,然后再让n=n/5,相当于把这部分的因式分解出来的5全除掉(因为结果已经更新,后面计算不需要这些),然后对此时n我们再算有多少5可以分解出来,此时用的是同样的方法。(相当于一直用方法1的step1)。相当于分解成子问题把。
这样做的好处是,n/5显然比算5^i要容易一些。
最后注意一下n=0的处理。
方法1,2时间复杂度都是O(log5(N)),空间复杂度O(1)
更多leetcode算法题解法: 专栏 leetcode算法从零到结束 或者 leetcode 解题目录 Python3 一步一步持续更新~
三.源码
emmm,也提供一下阶乘的方法,放末尾
方法一:
import math
class Solution:
def trailingZeroes(self, n: int) -> int:
if n==0:return 0
return sum([n//5**i for i in range(1,int(math.log(n,5))+1)])
方法二:
class Solution:
def trailingZeroes(self, n: int) -> int:
res=0
while n:
res+=n//5
n//=5
return res
方法三:算阶乘,超时
# version1
from itertools import accumulate
import operator
class Solution:
def trailingZeroes(self, n: int) -> int:
if n==0:return 0
res,n_fac=0,list(accumulate(range(1,n+1),operator.mul))[-1]
while n_fac:
if n_fac%10==0:
res+=1
n_fac//=10
else:break
return res
# version2
class Solution:
def trailingZeroes(self, n: int) -> int:
if n==0:return 0
res,n_fac=0,self.factorial(n)
while n_fac:
if n_fac%10==0:
res+=1
n_fac//=10
else:break
return res
def factorial(self,n):
if n==1:return 1
else:return n*self.factorial(n-1)