前言
Leetcode 面试题16.05,题目本身很有意思,但官方题解比较晦涩难懂,本博客可以帮助理解算法的实现思路。看完之后绝对让你感叹:“不愧是简单题目!”
题目解读
面试题 16.05. 阶乘尾数 - 力扣(LeetCode)
题目本身很简单,甚至都不要怎么解释,就是计算阶乘答案的最后有几个‘0’。直接模拟的话,很简单,伪代码表示如下:
输入 n;
num = n!; //计算阶乘
while(num)
if num的最后一位是为‘0’
cot++;
n = n / 10
这样解这道题,问题也很显而易见,就是当n
较大时,num
会溢出,进而无法通过循坏来求得最后的答案,因此我们需要从其他角度出发,优化我们的算法。
算法思路
重新转化一下这道题要求的结果:
一个数num
的尾随0,可以看作是一个数num
不断乘10产生的。所以,我们求尾随0,就转化为求一个数的因数中有几个10。同时10=2*5
,这意味着,在将一个数完全分解为质因数的乘积后,有几个5,原数的因数就有几个10。(一个数完全分解为质因数的乘积后,质因数2的数量一定大于质因数5的数量)
num = n! = 1 * 2 * ··· * n
阶乘本身就是n个因数的乘积,由此我们可以发现规律:
-
每5个数,就会有一个质因数5出现(5, 10, 15 ···)
-
每25个数,就会有两个质因数5出现 25 = 5*5 (25, 50, 75 ···)
-
每125个数,就会有三个质因数5出现 125 = 5 * 5 * 5 (125, 250, 375 ···)
···
综上,我们的最终答案就可以转变为 cot = n/5 + n/25 + n/125 + ···
伪代码:
输入n;
while(n>5) //当n小于5的时候就不可能再有因数5
cot依次加上n/5,n/25, ···
完整代码
class Solution {
public:
int trailingZeroes(int n) {
int cot=0;
while(n > 5){
n /= 5; //这样做防止了分母的溢出
//cot = n/5 + n/5/5 + ···
cot += n;
}
return cot;
}
};