zoukankan      html  css  js  c++  java
  • [LeetCode#204]Factorial Trailing Zeroes

    Problem:

    Description:

    Count the number of prime numbers less than a non-negative number, n.

    Analysis:

    The idea to test if a number is prime.
    Reference:
    https://en.wikipedia.org/wiki/Prime_number
    
    Prime number is an important category of problems. 
    It is not hard, but require some skills in implementing.
    
    A trivial idea for solving this problem is, test every number from "2" to "n-1" individually.
    The imprtant part of this idea is how to test if a number is prime number.
    
    One simple pattern is:
    Checking if a num could be divided by an integer(larger than 1), if it is, it is not a prime number.
    Definition: A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
    A solution:
    private boolean testPrime(int num) {
            if (num < 2)
                return false;
            for (int i = 2; i <= num / 2; i++) 
                if (num % i == 0)
                    return false;
            }
            return true;
    }
    
    We need to stop i at num/2, since after that : num / i < 2 (a fractation (2, 1]). 
    
    Actually, we stop i more early, since "after num / sqrt(num) <= sqrt(num)" which means we repeat the checking if we cointue checking. 
    private boolean testPrime(int num) {
            if (num < 2)
                return false;
            for (int i = 2; i <= Math.sqrt(num); i++) {
                if (num % i == 0)
                    return false;
            }
            return true;
    }
    Cases: 
    num = 12.
    1. use "for (int i = 2; i <= num / 2; i++)"
    test: 2, 3, 4, 5, 6
    
    2. use "for (int i = 2; i <= Math.sqrt(num); i++)""
    test: 2, 3
    
    test (num % 2) is no differnet than test (num % 6)
    test (num % 3) is no different thant test (num % 4)
    To many repeatives in the unimproved solution.
    
    Exceed time solution:
    public class Solution {
        public int countPrimes(int n) {
            if (n < 2)
                return 0;
            int count = 0;
            for (int i = 2; i < n; i++) {
                if (testPrime(i))
                    count++;
            }
            return count;
        }
        
        private boolean testPrime(int num) {
            if (num < 2)
                return false;
            //for (int i = 2; i <= num / 2; i++) 
            for (int i = 2; i <= Math.sqrt(num); i++) {
                if (num % i == 0)
                    return false;
            }
            return true;
        }
    }
    
    -------------------------------------------------------------------
    The above solution is perfect in testing against a single integer, but for distinguishing a series of integers. The time cost is too high.
    Thus we have to use "Sieve of Eratosthenes" method.
    Reference:
    https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
    
    Basic idea:
    In the trivial solution, we repeatedly to check a integer against [2, ... celi(sqrt(i))]. All integer need to check against 2 , 3 ... again and again. Is that necessary, can we avoid it?
    
    Yes, by using a check_board, we check "forward" rather than "backward"!
    For a prime number p, we tag all its mulitple "p*2" "p*3" .... 
    Thus each number actually only check against with one number. 
    For the detail of the algorithm, please refer the reference link.
    
    Skill:
    1. if we tag sequentially, the left-most untagged number must be prime number. 
    Since all numbers smaller than it could not be a divisor of it (otherwise, the number was tagged). Not to say the number large than it.
    
    2. to tag non-prime number, we only need to start from "i^2" then "i^2+i" ...
    The reason is simple. all (i-1) * i has already been tested. 
    for (int j = i*i; j < n; j=j+i) {
        check_board[j] = false;
    }

    Efficient Soltuion:

    public class Solution {
        public int countPrimes(int n) {
            if (n < 2)
                return 0;
            boolean[] check_board = new boolean[n+1];
            //note this pitfall!!!
            Arrays.fill(check_board, true);
            int count = 0;
            for (int i = 2; i < n; i++) {
                if (i < Math.sqrt(n)) {
                    if (check_board[i] == false) {
                        continue;
                    } else{
                        count++;
                        for (int j = i*i; j < n; j=j+i) {
                            check_board[j] = false;
                        }
                    }
                } else {
                    if (check_board[i] == true)
                        count++;
                }
            }
            return count;
        }
    }

    Clear Solution:

    public class Solution {
        public int countPrimes(int n) {
            if (n < 2)
                return 0;
            boolean[] check_board = new boolean[n+1];
            //note this pitfall!!!
            Arrays.fill(check_board, true);
            int count = 0;
            for (int i = 2; i < n; i++) {
                if (i < Math.sqrt(n) && check_board[i] == true) {
                    for (int j = i*i; j < n; j=j+i) {
                        check_board[j] = false;
                    }
                } 
            }
            for (int i = 2; i < n; i++) {
                if (check_board[i] == true)
                    count++;
            }
            return count;
        }
    }
  • 相关阅读:
    PowerShell Arrays
    PowerShell Hashtable
    PowerShell Variables
    MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
    神奇的Timer
    神奇的Timer之lock篇
    利用lambda表达式正确关闭WCF连接
    Zendstutio设置
    一个服务器部署多个项目
    Magento模块配置文件
  • 原文地址:https://www.cnblogs.com/airwindow/p/4774739.html
Copyright © 2011-2022 走看看