每日一道 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 ...
随机推荐
- 学生成绩管理系统-JAVA语言测试
首先右键新建一个工程project 选择Java Project,单击next下一步 project命名为“学生成绩管理系统”,点击finish继续 右键src文件夹新建Package包,取名为te ...
- 在图像中隐藏数据:用 Python 来实现图像隐写术
什么是“隐写术”? 隐写术是将机密信息隐藏在更大的信息中,使别人无法知道隐藏信息的存在以及隐藏信息内容的过程.隐写术的目的是保证双方之间的机密交流.与隐藏机密信息内容的密码学不同,隐写术隐瞒了传达消息 ...
- Python 5 行代码的神奇操作
Python 语言实现功能直接了当,简明扼要,今天咱们就来一起看看 Python 5 行代码的神奇操作! 1.古典兔子问题 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语 ...
- Hive对字段进行urlDecode
最近项目中需要对埋点日志hive表进行分析,并且按一定的规则统计出来满足要求的用户pin.本来以为是一件比较简单的事,结果在查看导出的词表时发现很多带有"%"的明显具有url en ...
- C#开发笔记,点点细微,处处真情,记录开发中的难言之隐
该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/956 访问. 概述 本系列文章将会向大家介绍本人实际开发过程中所遇到技术 ...
- C#LeetCode刷题之#88-合并两个有序数组(Merge Sorted Array)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3686 访问. 给定两个有序整数数组 nums1 和 nums2, ...
- C#LeetCode刷题之#697-数组的度( Degree of an Array)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3738 访问. 给定一个非空且只包含非负数的整数数组 nums, ...
- Caused by: org.postgresql.util.PSQLException: 错误: 语法错误 在 "desc" 、语法错误 在 "from" 附近
此错误一般是由于postgres的数据库表字段名定义与关键字重名所致: 如下,创建的数据库表包含名称为“desc”的字段与倒叙查询的desc关键字冲突会导致Caused by: org.postgre ...
- 36 个JS 面试题
1.JS中let和const有什么用? 在现代js中,let&const是创建变量的不同方式. 在早期的js中,咱们使用var关键字来创建变量. let&const关键字是在ES6版本 ...
- 使用MSF通过MS17-010获取系统权限
---恢复内容开始--- Step1:开启postgresql数据库: /etc/init.d/postgresql start Step2:进入MSF中,搜索cve17-010相关的exp: sea ...