leetcode-172
作者:互联网
题目
给定一个整数 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}
aaaaaaaaaa
请问到了第
n
n
n行,总共会有多少个a
。
当然,我们的结论都是 ∑ i = 1 n i \sum_{i=1}^n i ∑i=1ni,但主要的问题是,你从哪里看的,按照行,还是按照列。
你可以说它就是每一行的数量,也可以说是每一列的数量,每一列的应该是
∑
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)2x=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