每日一道 LeetCode (41):阶乘后的零

每天 3 分钟,走上算法的逆袭之路。
前文合集
代码仓库
GitHub: https://github.com/meteor1993/LeetCode
Gitee: https://gitee.com/inwsy/LeetCode
题目:阶乘后的零
给定一个整数 n,返回 n! 结果尾数中零的数量。
示例 1:
输入: 3
输出: 0
解释: 3! = 6, 尾数中没有零。
示例 2:
输入: 5
输出: 1
解释: 5! = 120, 尾数中有 1 个零.
说明: 你算法的时间复杂度应为 O(log n) 。
解题方案一:暴力计算
看到这道题,常人的思维最少应该有先把 n! 算出来,再通过 /10 来计算末尾有多少个 0 。
// 暴力硬算
public int trailingZeroes(int n) {
// 先定义第一个数字
BigInteger bi = BigInteger.ONE;
for (int i = 2; i <= n; i++) {
bi = bi.multiply(BigInteger.valueOf(i));
}
// 定义 0 出现的次数
int count = 0;
while (bi.mod(BigInteger.TEN).equals(BigInteger.ZERO)) {
bi = bi.divide(BigInteger.TEN);
count++;
}
return count;
}

我累个擦,直接超时了,然后看下测试用例,竟然执行到一个 4327 的数字,拿 4 位数出来算阶乘,就是计算机来算我都觉得累得慌,这个测试用例我服了,甘拜下风。
么得办法了,看答案吧,我这个智商也就只能想到这种方案了。
解题方案二:计算因子 5
先想一下,啥情况下能产生 0 ,最小的产生因子是 2 * 5 。
借用一个答案上的示例,42 * 75 = 3150 ,这个算式可以拆解如下:
42 = 2 * 3 * 7
75 = 3 * 5 * 5
42 * 75 = 2 * 3 * 7 * 3 * 5 * 5
这里面只出现了一对 2 和 5 ,所以结果只有一个 0 。
接着看另一个案例,比如求 19! ,这里面包含 5 的因子有 5 、10 、15 ,包含 2 的因子有2、4、6、8、10、12、14、16、18 。
可以看到的规律是每 5 个数字就会有一个包含 5 的因子,而在这 5 个数中间,肯定至少有一个包含 2 的因子,实际上是有 2 个,所以就不需要考虑 2 这个因子了,单纯的考虑 5 就好了,那么算法就演变成了我们需要寻找包含 5 的因子,代码如下:
// 计算因子 5
public int trailingZeroes_1(int n) {
int count = 0;
for (int i = 5; i <= n; i += 5) {
int current = i;
while (current % 5 == 0) {
count++;
current /= 5;
}
}
return count;
}

结果又超时了,我心态崩了啊,答案给的都是超时,看这个输入的数字, TM 18 亿,还敢输入数字再大点嘛。
接着刚才的答案往下看。
答案上还给出了另一种方案,不需要每次检查是否可以被 5 整除,还可以直接检查是否可以被 5 的次幂整除:
public int trailingZeroes_2(int n) {
int count = 0;
for (int i = 5; i <= n; i += 5) {
int powerOf5 = 5;
while (i % powerOf5 == 0) {
count += 1;
powerOf5 *= 5;
}
}
return count;
}
这个方案实际上和上面的方案是一样的,没什么本质的区别。
解题方案三:高效的计算因子 5
接着往下看,更加高效的计算方案。
看下面这个阶乘方案:
n! = 1 * 2 * 3 * 4 * (1 * 5) * ... * (2 * 5) * ... * (3 * 5) *... * n
我们的目标是计算出现了多少个 5 ,从上面这个公式看下来,每隔 5 个数就会出现一次,那么我们使用 n / 5 就可以计算出来。
但是还没有结束,接着看下面的公式变化:
... * (1 * 5) * ... * (1 * 5 * 5) * ... * (2 * 5 * 5) * ... * (3 * 5 * 5) * ... * n
从这个公式可以看出来,每隔 5 个数,出现一个 5 ,每隔 25 个数,出现 2 个 5 ,每隔 125 个数,出现 3 个 5 ,以此类推。。。
最终出现 5 的个数就是 n / 5 + n / 25 + n / 125 ... 。
题解到这一步就能开始写程序了:
// 更加高效的计算因子 5
public int trailingZeroes_3(int n) {
int count = 0;
while (n > 0) {
n /= 5;
count += n;
}
return count;
}

终于出结果了,我太难了,不过 LeetCode 把这道题的难度定成简单真的合适么。。。
每日一道 LeetCode (41):阶乘后的零的更多相关文章
- LeetCode 172. 阶乘后的零(Factorial Trailing Zeroes)
172. 阶乘后的零 172. Factorial Trailing Zeroes 题目描述 给定一个整数 n,返回 n! 结果尾数中零的数量. LeetCode172. Factorial Trai ...
- Leetcode 172.阶乘后的零
阶乘后的零 给定一个整数 n,返回 n! 结果尾数中零的数量. 示例 1: 输入: 3 输出: 0 解释: 3! = 6, 尾数中没有零. 示例 2: 输入: 5 输出: 1 解释: 5! = 120 ...
- Java实现 LeetCode 172 阶乘后的零
172. 阶乘后的零 给定一个整数 n,返回 n! 结果尾数中零的数量. 示例 1: 输入: 3 输出: 0 解释: 3! = 6, 尾数中没有零. 示例 2: 输入: 5 输出: 1 解释: 5! ...
- 【每天一题】LeetCode 172. 阶乘后的零
开源地址:点击该链接 题目描述 https://leetcode-cn.com/problems/factorial-trailing-zeroes 给定一个整数 n,返回 n! 结果尾数中零的数量. ...
- 每日一道 LeetCode (3):回文数
前文合集 每日一道 LeetCode 文章合集 题目:回文数 题目来源:https://leetcode-cn.com/problems/palindrome-number/ 判断一个整数是否是回文数 ...
- 每日一道 LeetCode (5):最长公共前缀
前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee: https://gitee.com ...
- 每日一道 LeetCode (8):删除排序数组中的重复项和移除元素
每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...
- 每日一道 LeetCode (14):数组加一
每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...
- 每日一道 LeetCode (15):二进制求和
每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...
随机推荐
- Python自动化爬取App数据
基本环境配置 版本:Python3 系统:Windows 需要安装: 1.JDK - Download JDK,Appium要求用户必须配置JAVA环境, 否则启动Seesion报错. 很多人学习py ...
- 14、Java文件操作stream、File、IO
1.文件操作涉及到的基本概念 File File类 是文件操作的主要对象中文意义就是 文件 顾名思意 万物皆文件,在计算上看到的所有东西都是文件保存,不管是你的图片.视频.数据库数据等等都是按照基本的 ...
- Java 多态 接口继承等学习笔记
Super关键字 1.子类可以调用父类声明的构造方法 : 语法:在子类的构造方法中使用super关键字 super(参数列表) 2.操作被隐藏的成员变量(子类的成员变量和父类的成员变量重名的说法)和 ...
- 「MoreThanJava」Day 5:面向对象进阶——继承详解
「MoreThanJava」 宣扬的是 「学习,不止 CODE」,本系列 Java 基础教程是自己在结合各方面的知识之后,对 Java 基础的一个总回顾,旨在 「帮助新朋友快速高质量的学习」. 当然 ...
- [深度学习] Pytorch(三)—— 多/单GPU、CPU,训练保存、加载模型参数问题
[深度学习] Pytorch(三)-- 多/单GPU.CPU,训练保存.加载预测模型问题 上一篇实践学习中,遇到了在多/单个GPU.GPU与CPU的不同环境下训练保存.加载使用使用模型的问题,如果保存 ...
- C#LeetCode刷题之#892-三维形体的表面积(Surface Area of 3D Shapes)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4136 访问. 在 N * N 的网格上,我们放置一些 1 * 1 ...
- python设计模式之适配器模式
python设计模式之适配器模式 结构型设计模式一个系统中不同实体(比如,类和对象)之间的关系,关注的是提供一种简单的对象组合方式来创造功能. 适配器模式( Adapter pattern)是一种结构 ...
- 解决 Could not resolve type alias 'com.deppon.gis.module.job.server.util.SdoGeometryTypeHandler'. 的办法
单元测试提示下面错误: 核心错误: Failed to parse mapping resource: 'file [D:\490993\安装程序\DPAP2.1\dpap_v2.0.1\dpap_v ...
- 手把手教你在win10下搭建pytorch GPU环境(Anaconda+Pycharm)
Anaconda指的是一个开源的Python发行版本,其主要优点如下: Anaconda默认安装了常见的科学计算包,用它搭建起Python环境后不用再费时费力安装这些包: Anaconda可以创建互相 ...
- excel表格,根据某一列的值对整行进行颜色填充
1.选中要影响的表格范围,选择 “条件格式”,选择 “新建规则” (2)选择 “使用公式确定要设置格式的单元格”,录入公式,选择 “ 格式”,注意: 公式为:=$H1="待解决" ...