这道题求一个数的阶乘的末尾的0的个数.
数的范围很大,在Java中达到了Long.MAX_VALUE的大小.那就说明直接去求阶乘无异于开了比嵌套for循环的时间复杂度更大的情况,所以名义上要求阶乘,实际上不能够去求阶乘.这就需要我们再去把握数的规律.发现推理数的规律—和5的关系.从而去解决掉它!
我刚开始看看暴力写的话能过几个,看来是一个也过不了~hh,最小通过的限制的数据范围也在10e6的附近,hh
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long k = sc.nextLong();
//N的条件:一个是最小的,一个是自己的阶乘末尾k个0;不存在输出-1;
//首先处理数值的大小问题,这直接决定时间复杂度的大小.
//首先暴力试一下能过几个---一个也过不了,
//所以就要考虑用查找的算法---二分,二分的对象是N.
long l = 1, r = Long.MAX_VALUE - 1;//最大数中二分查找,去查找N,查找不到就返回-1;
while(l < r){//10(N)的阶乘后面有2(K)个0
long mid = (l + r ) / 2 ;//这个数是根据k的范围计算的,应该和k进行比较,
if(find(mid) < k) l = mid + 1;
else r = mid ;
}
if(find(r) == k) System.out.println(r);
else System.out.println(-1);
sc.close();
}
public static long find(long mid){//查找能够被5整除的个数
long res = 0;
while(mid != 0){
res += mid/5;
mid/=5;
}
return res;
}
}
发现数的规律后,知道它和5的倍数有关,得到了logn的时间复杂度.
又使用了二分,又是logn的时间复杂度