leetcode 172. Factorial Trailing Zeroes 非阶乘 python3

一.问题描述

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)
发布了218 篇原创文章 · 获赞 191 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/CSerwangjun/article/details/103396829