每天 3 分钟,走上算法的逆袭之路。

前文合集

每日一道 LeetCode 前文合集

代码仓库

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):阶乘后的零的更多相关文章

  1. LeetCode 172. 阶乘后的零(Factorial Trailing Zeroes)

    172. 阶乘后的零 172. Factorial Trailing Zeroes 题目描述 给定一个整数 n,返回 n! 结果尾数中零的数量. LeetCode172. Factorial Trai ...

  2. Leetcode 172.阶乘后的零

    阶乘后的零 给定一个整数 n,返回 n! 结果尾数中零的数量. 示例 1: 输入: 3 输出: 0 解释: 3! = 6, 尾数中没有零. 示例 2: 输入: 5 输出: 1 解释: 5! = 120 ...

  3. Java实现 LeetCode 172 阶乘后的零

    172. 阶乘后的零 给定一个整数 n,返回 n! 结果尾数中零的数量. 示例 1: 输入: 3 输出: 0 解释: 3! = 6, 尾数中没有零. 示例 2: 输入: 5 输出: 1 解释: 5! ...

  4. 【每天一题】LeetCode 172. 阶乘后的零

    开源地址:点击该链接 题目描述 https://leetcode-cn.com/problems/factorial-trailing-zeroes 给定一个整数 n,返回 n! 结果尾数中零的数量. ...

  5. 每日一道 LeetCode (3):回文数

    前文合集 每日一道 LeetCode 文章合集 题目:回文数 题目来源:https://leetcode-cn.com/problems/palindrome-number/ 判断一个整数是否是回文数 ...

  6. 每日一道 LeetCode (5):最长公共前缀

    前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee: https://gitee.com ...

  7. 每日一道 LeetCode (8):删除排序数组中的重复项和移除元素

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

  8. 每日一道 LeetCode (14):数组加一

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

  9. 每日一道 LeetCode (15):二进制求和

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

随机推荐

  1. 【MySQL】如何最大程度防止人为误操作MySQL数据库?这次我懂了!!

    写在前面 今天,一位哥们打电话来问我说误操作了他们公司数据库中的数据,如何恢复.他原本的想法是登录数据库update一个记录,结果忘了加where条件,于是悲剧发生了.今天,我们不讲如何恢复误操作的数 ...

  2. Take C# 8.0 for a spin

    本文章为机器翻译.https://blogs.msdn.microsoft.com/dotnet/2018/12/05/take-c-8-0-for-a-spin/ 以C # 8兜风 我们昨天宣布Vi ...

  3. C#LeetCode刷题之#459-重复的子字符串(Repeated Substring Pattern)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3945 访问. 给定一个非空的字符串,判断它是否可以由它的一个子串 ...

  4. 解Bug之路-dubbo流量上线时的非平滑问题

    前言 笔者最近解决了一个困扰了业务系统很久的问题.这个问题只在发布时出现,每次只影响一两次调用,相较于其它的问题来说,这个问题有点不够受重视.由于种种原因,使得这个问题到了业务必须解决的程度,于是就到 ...

  5. SourceTreet提交时显示remote: Incorrect username or password ( access token )(4种解决办法)

    引言 我因为第一次安装Sources Tree的时候进行破解时(跳过安装时的登录),因为操作失误造成了好多bug,导致Sources Tree不论提交,拉取,获取,都会报remote: Incorre ...

  6. 如何限制ip访问Oracle数据库

    一.概述 本文将给大家介绍如何限制某个ip或某个ip段才能访问Oracle数据库 通过sqlnet.ora 通过/etc/hosts.deny和/etc/hosts.allow 通过iptables ...

  7. dpkg:处理 xxx (--configure)时出错解决办法

    1.$ sudo mv /var/lib/dpkg/info /var/lib/dpkg/info_old //现将info文件夹更名2.$ sudo mkdir /var/lib/dpkg/info ...

  8. Centos7 KVM启用嵌套虚拟化

    [root@kvm-hypervisor ~]# cat /etc/modprobe.d/kvm-nested.conf options kvm-intel nested= options kvm-i ...

  9. 微服务项目整合Ocelot+IdentityServer4

    项目搭建肯定少不了认证和授权,传统的单体应用基于cookie和session来完成的. 因为http请求是无状态的,每个请求都是完全独立的,服务端无法确认当前请求之前是否登陆过.所以第一次请求(登录) ...

  10. 利用python爬取贝壳网租房信息

    最近准备换房子,在网站上寻找各种房源信息,看得眼花缭乱,于是想着能否将基本信息汇总起来便于查找,便用python将基本信息爬下来放到excel,这样一来就容易搜索了. 1. 利用lxml中的xpath ...