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;
        }
    }
  • 相关阅读:
    POJ 3258 (NOIP2015 D2T1跳石头)
    POJ 3122 二分
    POJ 3104 二分
    POJ 1995 快速幂
    409. Longest Palindrome
    389. Find the Difference
    381. Insert Delete GetRandom O(1)
    380. Insert Delete GetRandom O(1)
    355. Design Twitter
    347. Top K Frequent Elements (sort map)
  • 原文地址:https://www.cnblogs.com/airwindow/p/4774739.html
Copyright © 2011-2022 走看看