算法学习之旅

来源:互联网 发布:h5模板源码下载 编辑:程序博客网 时间:2024/05/15 09:36

问题:设计一个算法,计算出n阶乘中尾部零的个数
例如: 11! = 39916800,因此应该返回 2
挑战:O(logN)的时间复杂度

想法1:
找出1–n中每个数字能够被5或者10整除的次数,加在一起就是答案。但是时间复杂度是O(N2).代码如下:`public static long trailingZeros(long n) {
// write your code here
long five=0;
long count=0;
for(long i=1;i<=n;i++){
if(i%10==0){
long j=i;
while(j>1 && j%10==0){
j/=10;
count++;
}
if(j%5==0){
while(j>1 && j%5==0){
j/=5;
count++;
}
}
}else if(i%5==0){
long k=i;
while(k>1 && k%5==0){
k/=5;
count++;
}
}

     }     return count;}

想法2.统计1—n 能被5整除的次数,累加求和,代码类似上边

想法3:对想法2进行优化,只对1—n之中能够被5整除的数进行统计。代码如下:
public static long trailingZeros(long n) {
// write your code here
long five=0;
long count=0;
if(n<5){
return 0;
}else if(n==5){
return 1;
}
for(long i=5;i<=n;i+=5){
if(i%5==0){
long j=i;
while(j>0 && j%5==0){
j/=5;
count++;
}
}
}
return count;
}
《编程之美》上的想法3:
公式:Z = [N/5] +[N/52] +[N/53] + …(不用担心这会是一个无穷的运算,因为总存在一个K,使得5K > N,[N/5K]=0。)
5的倍数贡献一个5,5的平方贡献两个5~~~.
代码如下:
int num = 0, i;
for(i=5; i<=n; i*=5)
{
num += n/i;
}
return num;
又简洁,执行效率又高,与君共勉之。

0 0
原创粉丝点击