今天带给大家的这道题目是一道非常有趣的算法题目,在LeetCode上面是一道简单题目,但是自己要独立的解出来还是有一定难度的,需要一点数学和编程基础。那么就带领大家一起看看解这道题目的思路吧!
![be38050bd3d86e0714ac2ced7e86afe4.png](https://i-blog.csdnimg.cn/blog_migrate/3db5ec00d21fa86518aedd798286f04e.jpeg)
题目描述:设计一个算法,计算出n阶乘中尾部零的个数?
样例 1:输入: 11输出: 2样例解释: 11! = 39916800, 结尾的0有2个。样例 2:输入: 5输出: 1样例解释: 5! = 120, 结尾的0有1个。
挑战
O(logN)的时间复杂度
![cb5a690ef7b1214a069813e985dee0ce.png](https://i-blog.csdnimg.cn/blog_migrate/23e5e6023fb83424f9214a3fececd8d9.jpeg)
题目分析
上面已经给出了完整的题目描述,拿到这个题后,大家第一直觉就是先求出N!的结果是多少,然后再判断结果末尾0的数量
第一种思路:先求结果,在判断末尾0的数量
- 时间复杂度不符合要求,该思路为O(n),不符合题目要求
- 计算开销太大,100!的结果是多少?1000?1000000?
- 溢出问题,很容易超出long型整数
第一种思路显然不对,必须另想方法,既然我们要计算尾数中的零的个数,等价于我们要计算 n! 中含有多少个 10 这个因子,再进一步的说,10 = 2 * 5,这两个因子已无法再分解了。所以原问题再次等价于计算 n! 中含有多少对 (2, 5) 因子。
![44b681c47a86f57f8e888b1661704222.png](https://i-blog.csdnimg.cn/blog_migrate/4d2cae4895e705930f06dd4deb26f798.jpeg)
第二种思路:计算 n! 中含有多少对 (2, 5) 因子
很显然,在 n! 中 2 这个因子,出现的次数肯定 >= 5 出现的次数,所以原问题又等价于计算 n! 中因子 5 出现的次数,因此选择以5为迭代步数即可。 这样做比上面要快5倍。该思路的时间复杂度O(n/5),已经很快了,但是还是和题目中的挑战有差距。
//思路二:代码实现 class Solution {public: long long trailingZeros(long long n) { // write your code here, try to do it without arithmetic operators. long count = 0; long pwr = 25; for (long temp = 5; temp <= n; temp+=5) { count++; pwr = 25; while (temp % pwr == 0) { count++; pwr *= 5; } } return count; }};
第三种思路:计算 n! 中因子 5 出现的次数,换种思路思考
原问题又等价于计算 n! 中因子 5 出现的次数,所有可能出现在含有 5 的数如下:
5^1, 5^2, 5^3, 5^4, 5^5..., 5^max_exp
所以该题的解就是计算如下结果:
(n/5^1 + n/5^2 + n/5^3 + n/5^4 + n/5^5 + ... + n/5^max_exp)
//第三种思路代码实现,c++class Solution {public: long long trailingZeros(long long n) { // write your code here, try to do it without arithmetic operators. long count = 0; long temp = n/5; while(temp != 0){ count += temp; temp /= 5; } return count; }};
关注不迷路,免费学算法。后面会给大家带来更多的有关于编程,算法的文章和视频。欢迎评论交流哦!