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

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

题目要求

在这里插入图片描述

思路

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

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

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

  • p p p的倍数有 c n t 1 = ⌊ n p ⌋ cnt_1=\lfloor \frac{n}{p} \rfloor cnt1=pn个;
  • p 2 p^2 p2的倍数有 c n t 2 = ⌊ n p 2 ⌋ cnt_2=\lfloor \frac{n}{p^2} \rfloor cnt2=p2n个;
  • ……
    越往下数其实是越少的,很明显是 p 2 p^2 p2的倍数也会是 p p p的倍数,避免重复统计,只加多出来的 p p p就可以, [ 1 , n ] [1,n] [1,n]中质因子 p p p的个数为 ∑ k = 1 ∞ ⌊ n p k ⌋ \sum_{k=1}^\infty\lfloor \frac{n}{p^k}\rfloor k=1pkn

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

Java

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

C++

class Solution {
public:
    int trailingZeroes(int n) {
        return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
    }
};
  • 时间复杂度: O ( log ⁡ n ) O(\log n) O(logn)
  • 空间复杂度: O ( 1 ) 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 ( log ⁡ n ) O(\log n) O(logn)
  • 空间复杂度: O ( 1 ) O(1) O(1)

总结

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


欢迎指正与讨论!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值