一、题目描述
Given an integer n, return the number of trailing zeroes in n!.
Example 1:
Input: 3
Output: 0
Explanation: 3! = 6, no trailing zero.
Example 2:
Input: 5
Output: 1
Explanation: 5! = 120, one trailing zero.
Note: Your solution should be in logarithmic(对数) time complexity.
二、题解
(1) 暴力(超时,使用int存储会溢出)
/**
* 暴力破解(超时):ret不用long会溢出。
* @param n
* @return
*/
public int trailingZeroes1(int n) {
int count=0;
long ret=0;
for (int i = n; i >= 1; --i) {
ret *= n;
n--;
}
while(n != 0) {
if(n % 10 == 0) count++;
n/=10;
}
return count;
}
复杂度分析
- 时间复杂度:
- 空间复杂度:
(2) 暴力优化(数学思想 | 超时)
计算 N 的阶乘 有多少个后缀0,即计算 里有多少个 ,也就是计算 里有多少个 和
- 数学原理:分解质因数,最后结果即 2 的个数和 5 的个数取较小值。
- 因此,得到下面时间复杂度为 的暴力求解的算法。
- 这种求法不会阶乘时的溢出。
/**
* @date: 1/17/2020 5:09 PM
* @Execution info:
* ·执行用时 ms 击败了 % 的java用户
* ·内存消耗 MB 击败了 % 的java用户
* @Asymptotic Time Complexity:O()
*/
public int trailingZeroes2(int n) {
int cnt2=0;
int cnt5=0;
for (int i = 2; i <= n; i++) {
int t=i;
while(t%2 == 0) {
cnt2++;
t>>=1;
}
while(t%5==0) {
cnt5++;
t/=5;
}
}
return cnt2 > cnt5 ? cnt5 : cnt2;
}
复杂度分析
- 时间复杂度:
- 空间复杂度:
(3) 纯数学求解
暴力的解法对于特殊的数学问题一般会超时,但却不是一无是处,可用于前期查找规律,为之后提供数据和思路。于是,我们就有了下面这些思想。
- 的来源 所以一对 2 和 5 即可产生一个 0,所以 0 的个数即为 ,
- 又因 2 的倍数的数一定比是 5 的倍数的数多,所以 2 的个数一定 >=5 的个数,所以只需要统计 5 的个数
- 每隔 5 个数就会有一个含有因子5 的元素,但是这些元素中每隔 5 个会多一个因子5(即, ),如 ,这些因子中 就又多一个因子5,
- 其实就是求 的和。迭代,先求 ,完事再其基础上再除以 5 来求 等等
/**
* @date: 1/17/2020 5:28 PM
* @Execution info:
* ·执行用时 1 ms 击败了 100% 的java用户
* ·内存消耗 33MB 击败了 89.8% 的java用户
* @Asymptotic Time Complexity:O()
*/
public int trailingZeroes3(int n) {
int count=0;
while(n >= 5) {
count += n/5;
n/=5;
}
return count;
}
复杂度分析
时间复杂度:
空间复杂度: