zoukankan      html  css  js  c++  java
  • Leetcode: Factorial Trailing Zeroes

    Given an integer n, return the number of trailing zeroes in n!.
    
    Note: Your solution should be in logarithmic time complexity.

    Naive方法:A simple method is to first calculate factorial of n, then count trailing 0s in the result (We can count trailing 0s by repeatedly dividing the factorial by 10 till the remainder is 0). 但这样做的显著缺点是:can cause overflow for a slightly bigger numbers as factorial of a number is a big number (See factorial of 20 given in above examples). 

    转自GeeksforGeeks的想法:The idea is to consider prime factors of a factorial n. A trailing zero is always produced by prime factors 2 and 5. If we can count the number of 5s and 2s, our task is done. Consider the following examples.

    n = 5: There is one 5 and 3 2s in prime factors of 5! (2 * 2 * 2 * 3 * 5). So count of trailing 0s is 1.

    n = 11: There are two 5s and eight 2s in prime factors of 11! (2 8 * 34 * 52 * 7). So count of trailing 0s is 2.

    我们会发现: the number of 2s in prime factors is always more than or equal to the number of 5s. So if we count 5s in prime factors, we are done. 

    How to count total number of 5s in prime factors of n!? A simple way is to calculate floor(n/5). 

    问题转化为求阶乘过程中质因子5的个数,但是要注意25能提供2个5,125能提供3个5....

    所以,count= floor(n/5) + floor(n/25) + floor(n/125) + ....

     1 public class Solution {
     2     public int trailingZeroes(int n) {
     3         int count = 0;
     4         for (int i=5; (n/i)>=1;) {
     5             count += n / i;
     6             n /= 5;
     7         }
     8         return count;
     9     }
    10 }

    最开始我的写法是:

     1 // Function to return trailing 0s in factorial of n
     2 int findTrailingZeros(int  n)
     3 {
     4     // Initialize result
     5     int count = 0;
     6  
     7     // Keep dividing n by powers of 5 and update count
     8     for (int i=5; n/i>=1; i *= 5)
     9           count += n/i;
    10  
    11     return count;
    12 }

    在oj上提交会发现n =  1808548329时出错了,期望答案是452137076,实际答案是452137080

    原因就是 i*5一直连乘时出现i = 5^14时,内存溢出(5^13 = 1220703125 < 2^31, but 5^14 = 6103515625 > 2^32)

    Integer overflow之后会wrap around, 即Integer.MAX_VALUE + 1会成为Integer.MIN_VALUE, 详见Why Integer overflows wrap around

    6103515625 wrap around之后 为正的1808548329-1 = 1808548328

    原因是6103515625 % 2^32 = 1808548329 < 2 ^31,即 i 比32位Integer(共2^32)多出1808548329个数, 为 1808548328,又可以再进一次for 循环(本不应该进的)。所以答案偏大

    解决办法:用除法代替乘法,用n / 5代替 i * 5,防止overflow,如最上面那段code所示

  • 相关阅读:
    关于dubbo创建服务和引用服务时,会报错:cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element 问题的解决
    解决 Maven工程运行报错Failed to clean project: Failed to delete
    Linux学习_004_使用CentOS 7.5卸载自带jdk安装自己的JDK1.8
    Linux下的JDK和OpenJDK有什么具体的区别
    常用的大数据技术有哪些?
    如何隐藏你的 Linux 的命令行历史
    Securi-Pi:使用树莓派作为安全跳板
    在 Linux 上管理加密密钥的最佳体验
    在 Linux 下使用任务管理器
    在 Linux 中安装 Lighttpd Web 服务器
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/4207498.html
Copyright © 2011-2022 走看看