ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

leetcode-172

2021-02-08 11:31:35  阅读:204  来源: 互联网

标签:count 25 return int trailingZeroes 172 因子 leetcode


题目

给定一个整数 n,返回 n! 结果尾数中零的数量。

爆破

class Solution:
    def trailingZeroes(self, n: int) -> int:
        result = reduce(lambda x,y:x*y, [x for x in range(1, n+1)])
        count = 0
        while result % 10 == 0:
            count += 1
            result /= 10
        return count

遇见问题需要关注两个点

  • 问题究竟是什么
  • 方法究竟干什么

有时候,题干中有很多垃圾,它的作用只是用来进行误导,也可能毫无作用。

思考时,一方面可能受垃圾影响,导致范围扩大,一方面由于思想收束,丢失部分信息。

两个方面需要进行对比衡量,才能做到快速和准确。

规律

有多少个0,意味着能够阶段的被10整除,但是垃圾在于,我们是否一定需要n!

九真一假,才能骗到人。

有用的信息,不一定就能够直接用,n!并不很好用。

升华到10以后,我们可以看见,对于整体的判断可以分割到步骤中。

这样,重叠的两个部分采用同一个逻辑,必然更加快速。


根据这个思路,可以进行两层的深入

  • 因子的针对

    由于是n!,每一个因子都是会和其他的进行组合的,我们需要细化到2-5的配对组合

  • 单独收集

    5 5 5的周期大于 2 2 2,因此配对情况总是以最少的为准,也就是 5 5 5的个数

class Solution:
    def trailingZeroes(self, n: int) -> int:
        count_5 = 0
        for i in range(1, n+1):
            if i % 5 == 0:
                count_5 += 1
        return count_5

但是,25这种,隐含的多重的5的因子,需要多重的计算

25 × 2 = 50 25 = 5 × 5 25 \times 2 = 50 \\ 25 = 5 \times 5 25×2=5025=5×5

配对以后还能配对

class Solution:
    def trailingZeroes(self, n: int) -> int:
        count_5 = 0
        for i in range(1, n+1):
            while i % 5 == 0:
                count_5 += 1
                i //= 5
        return count_5

命中

其实有个很简单的道理,如果不是 5 5 5的倍数,必然不能被 5 5 5整除,不是 5 5 5的倍数,我们就不必要关注

class Solution:
    def trailingZeroes(self, n: int) -> int:
        count_5 = 0
        for i in range(0, n+1, 5):
            while i % 5 == 0:
                count_5 += 1
                i //= 5
        return count_5

这样,需要计算的数据大概就是原来的 1 5 \frac{1}{5} 51​了。

角度

什么时候会重复生成因子 5 5 5?

可以考察一下下面几组数据

  • 1 2 3 4 5
  • 6 7 8 9 10
  • 21 22 23 24 25

也就是说,基础组的 5 5 5来源于步进的倍数,但是如果是 5 5 5次的 5 5 5步进,就会诞生多重的 5 5 5。


可以先来回顾两个简单问题

堆积
a a a a a a a a a a \begin{matrix} &a &\\ &a &a &\\ &a &a &a &\\ &a &a &a &a \end{matrix} ​aaaa​aaa​aa​a​
请问到了第 n n n行,总共会有多少个a

当然,我们的结论都是 ∑ i = 1 n i \sum_{i=1}^n i ∑i=1n​i,但主要的问题是,你从哪里看的,按照行,还是按照列。

你可以说它就是每一行的数量,也可以说是每一列的数量,每一列的应该是
∑ i = 1 n ( n − i + 1 ) \sum_{i=1}^n (n-i+1) i=1∑n​(n−i+1)
两种思路在这道题中是一致的,但是第一种并不具备拓延性,接下来拓展一下


x n = { x x = 1 x × x n − 1 o d d ( x n 2 ) 2 e v e n x^n = \left\{ \begin{matrix} x & x = 1 \\ x \times x^{n-1} & odd \\ (x^{\frac{n}{2}})^2 & even \end{matrix} \right. xn=⎩⎨⎧​xx×xn−1(x2n​)2​x=1oddeven​
想象一下,这会让我们操作降低多少,基本上就是操作减半,也就是 O ( lg ⁡ n ) \Large O(\lg n) O(lgn)

但是,关注一下它的跨度,列举一下

  • 1 2
  • 1 2 3 4
  • 1 2 3 4 5 6 7 8

它把每次的逐渐进行翻倍,但是最终结果是保留的。


现在,回顾一下初心,我们需要计算的是因子 5 5 5的个数,它也应该有层级的划分

  • 一层因子
  • 二层因子

根据 n n n,我们可以知道一层因子 5 5 5的数量是 n / / 5 n // 5 n//5。

二级因子呢,也就是以一级的 5 5 5的一组的 5 5 5的步进,三级四级依次递增。

这就很好的揭示了为什么有些数字会显得比较特殊,有多层的 5 5 5,因为他们的重复次数存在叠加。

class Solution:
    def trailingZeroes(self, n: int) -> int:
        if n < 5:
            return 0
        return (n // 5) + self.trailingZeroes(n // 5)

使用递归,分别计算每一层的 5 5 5的周期即可。

标签:count,25,return,int,trailingZeroes,172,因子,leetcode
来源: https://blog.csdn.net/wait_for_eva/article/details/113753949

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有