阶乘尾部的0

每天一道算法题

问题

  • 描述:
    • 设计一个算法,计算出 n 阶乘中尾部 0 的个数。(不考虑 n = 0)
  • 挑战:
    • O(logN)的时间复杂度

解决

首先我们不考虑时间复杂的解决思路是先求出 n 的阶乘,然后再计算 n 阶乘尾部 0 的个数。

代码如下:

public long trailingZeros(long n) {
     long arg = 1;
     long result = 0;
     //求 n 的阶乘  
     for (int i = 2; i <= n; i++) {
          arg *= i;
     }
     //求尾部 0 的个数
     while (arg % 10 == 0) {
          if (arg == 0) {
               return result;    
          }   
          ++result;
          arg /= 10;
     }
     return result;
}

时间复杂度为 O(N)。那如何才能使时间复杂度为 O(logN) 呢?

先求阶乘,然后再求尾部 0 的个数肯定不行。所以我们必须找出 n 与 n 阶乘尾部 0 的个数之间的关系。

我们将 n 阶乘中每个数拆成素因子的乘积,发现尾部的 0 是由 2*5 产生的,而 5 的量一定小于 2,因此素因子中 5 的个数决定了尾部 0 的个数,只要求出 n 阶乘中素因子 5 的出现次数即可。

11 ! = 11 * 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1

= 11 * 2*5 * 3*3 * 2*2*2 * 7 * 2*3 * 5 * 2*2 * 3 * 2 * 1 (其中素因子 5 有 2 个)

= 39916800 (尾部有 2 个 0)

代码如下

public long trailingZeros(long n) {
     long result = 0;
     while (n >= 5) {
         n /= 5;
         result += n;
     }
     return result;
}
原文请点击
posted @ 2020-04-21 00:42  GoodBoyDing  阅读(19)  评论(0)    收藏  举报