Java&C++题解与拓展——leetcode172.阶乘后的零【一行代码结束、没啥新知识】

118 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

每日一题做题记录,参考官方和三叶的题解

题目要求

image.png

思路

对于阶乘来讲,尾巴的零是由展开式里55的数量决定的。因为只有2×52\times 5可以得到1010,造出尾巴里的零,那很明显22的数量要比55多,所以只要统计55的数量就好了。

至此,题目变成了统计质因数。拆分质因数最终会获得一个类似于…(2*3)…(2*5)…的算式,在后面数越来越大的时候会出现…(2*3*3)…(2*5*5)…等类似的情况,甚至于(2*5*5*5)等。也就是说每隔5个数会有一个55需要统计,每个25个数会有两个55需要统计(多一个55需要统计),每125个数会有三个55需要统计(再多一个)……把它们加起来就是答案。

[1,n][1,n]的范围内:

  • pp的倍数有cnt1=npcnt_1=\lfloor \frac{n}{p} \rfloor个;
  • p2p^2的倍数有cnt2=np2cnt_2=\lfloor \frac{n}{p^2} \rfloor个;
  • …… 越往下数其实是越少的,很明显是p2p^2的倍数也会是pp的倍数,避免重复统计,只加多出来的pp就可以,[1,n][1,n]中质因子pp的个数为k=1npk\sum_{k=1}^\infty\lfloor \frac{n}{p^k}\rfloor

代码实现起来其实就直接递归了,两种语言是一样的😂,就顺手写了下python。

Java

class Solution {
    public int trailingZeroes(int n) {
        return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
    }
}
  • 时间复杂度:O(logn)O(\log n)
  • 空间复杂度:O(1)O(1),忽略递归的额外空间开销

C++

class Solution {
public:
    int trailingZeroes(int n) {
        return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
    }
};
  • 时间复杂度:O(logn)O(\log n)
  • 空间复杂度:O(1)O(1)

Python

class Solution:
    def trailingZeroes(self, n: int) -> int:
        return n // 5 + self.trailingZeroes(n // 5) if n else 0
  • 时间复杂度:O(logn)O(\log n)
  • 空间复杂度:O(1)O(1)

总结

一道纯靠数学思路的题目,源头就是找因子55的个数,初拿到手还在想怎么快速判断那么多个数都是55的多少次,然后反应过来一路除下去加起来就好了。


欢迎指正与讨论!