判斷一個數(shù)是否是質(zhì)數(shù)的算法

對于一個大于1的整數(shù),如果其除數(shù)只有1和它本身,那么它就是一個質(zhì)數(shù)

判斷一個數(shù)是否為質(zhì)數(shù)

窮舉法

  • 窮舉法,檢測2,3,4,5...,n-1能夠整除n。如果不能,那么n就是素數(shù)。這個算法耗費O(n)來檢測n是否是一個素數(shù)。
public static boolean isPrimeNumber(int n){
        if (n < 2) {
            return false;
        }
        for (int i = 2; i <= n-1; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

時間復(fù)雜度為O(n)

稍微改進的算法

  • 稍微注意一下,只需檢測2,3,4,5...n/2是否能整除n。如果不能那么n就是素數(shù)。算法效率只是稍微提高了一點,它的時間復(fù)雜度依舊是O(n)
public static boolean isPrimeNumber1(int n) {
        if (n < 2) {
            return false;
        }
        for (int i = 2; i <= n / 2; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

高效算法

  • 實際上我們可以證明,如果n不是素數(shù),那么n必須有一個大于1且小于或者等于√n。證明過程:
    因為n不是素數(shù),所以會存在兩個數(shù)p和q,滿足n=pq且1<p≤q。注意到n=√n*√n。p必須小于等于√n。

    因此只需要檢測2,3,4,5,...,√n是否能被n整除。如果不能,n就是素數(shù)。這會顯著的降低時間復(fù)雜度,為O(√n)。

public static boolean isPrimeNumber2(int n) {
        if (n < 2) {
            return false;
        }
        int squareRoot=(int) Math.sqrt(n);
        for (int i = 2; i <= squareRoot; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

上述開根號的效率較低,可以用以下方式代替。

public static boolean isPrimeNumber3(int n) {
        if (n < 2) {
            return false;
        }
        int squareRoot=1;
        while(squareRoot*squareRoot<n){
            squareRoot++;
        }
        for (int i = 2; i  <= squareRoot; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }

篩選出小于n內(nèi)所有質(zhì)數(shù)的

上述都是判斷一個大于1的自然數(shù)是否是素數(shù)的算法,對于篩選出小于自然數(shù)n內(nèi)的所有素數(shù),有一個更為高效的算法,埃拉托斯特尼篩法。這個算法求出所有小于或等于n的素數(shù)。

這個算法的原理是:一個質(zhì)數(shù)總是可以分解成若干個質(zhì)數(shù)的乘積,那么如果把質(zhì)數(shù)(最初只知道2是質(zhì)數(shù))的倍數(shù)都去掉,那么剩下的就是質(zhì)數(shù)了。

埃拉托斯特尼篩法

算法實現(xiàn):

/**
     * 運用埃拉托色篩選法篩選出所有小于等于n的質(zhì)數(shù)
     */
    public static boolean[] sieveOfEratosthenes(int n) {
        boolean[] isPrime = new boolean[n + 1];
        //初始化,默認所有都是質(zhì)數(shù)
        for (int i = 0; i <= n; i++) {
            isPrime[i] = true;
        }
        //篩選,將所有質(zhì)數(shù)的倍數(shù)都標記為非質(zhì)數(shù)(最初只知道2是質(zhì)數(shù))
        for (int i = 2; i <= n / i; i++) {
            if (isPrime[i]) {
                for (int j = 2; j <= n/i; j++) {
                    isPrime[i * j] = false;
                }
            }
        }
        return isPrime;
    }

給出總的程序代碼:

/**
 * @author: gethin
 * @create: 2018-06-20 21:40
 * @description:
 **/
public class PrimeNumberJudge {
    
    /**
     * 窮舉法判斷是否為質(zhì)數(shù),時間復(fù)雜度O(n)
     */
    public static boolean isPrimeNumber(int n) {
        if (n < 2) {
            return false;
        }
        for (int i = 2; i <= n - 1; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 窮舉法稍微改進,時間復(fù)雜度O(n)
     */
    public static boolean isPrimeNumber1(int n) {
        if (n < 2) {
            return false;
        }
        for (int i = 2; i <= n / 2; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 高效算法,時間復(fù)雜度O(√n)
     */
    public static boolean isPrimeNumber2(int n) {
        if (n < 2) {
            return false;
        }
        int squareRoot = (int) Math.sqrt(n);
        for (int i = 2; i <= squareRoot; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 高效算法改進,時間復(fù)雜度O(√n)
     */
    public static boolean isPrimeNumber3(int n) {
        if (n < 2) {
            return false;
        }
        int squareRoot = 1;
        while (squareRoot * squareRoot < n) {
            squareRoot++;
        }
        for (int i = 2; i <= squareRoot; i++) {
            if (n % i == 0) {
                return false;
            }
        }
        return true;
    }
    
    /**
     * 運用埃拉托色篩選法篩選出所有小于等于n的質(zhì)數(shù)
     */
    public static boolean[] sieveOfEratosthenes(int n) {
        boolean[] isPrime = new boolean[n + 1];
        //初始化,默認所有都是質(zhì)數(shù)
        for (int i = 0; i <= n; i++) {
            isPrime[i] = true;
        }
        //篩選,將所有質(zhì)數(shù)的倍數(shù)都標記為非質(zhì)數(shù)(最初只知道2是質(zhì)數(shù))
        for (int i = 2; i <= n / i; i++) {
            if (isPrime[i]) {
                for (int j = 2; j <= n / i; j++) {
                    isPrime[i * j] = false;
                }
            }
        }
        return isPrime;
    }
    
    public static void main(String[] args) {
        int count = 0;
        Scanner input = new Scanner(System.in);
        System.out.print("輸入整數(shù)n:");
        int num = input.nextInt();
        System.out.println("\n運用改進的高效算法求小于等于n的所有質(zhì)數(shù)");
        for (int i = 0; i <= num; i++) {
            if (isPrimeNumber1(i)) {
                if (count % 10 == 0) {
                    System.out.println();
                }
                System.out.print(i + "\t");
                count++;
            }
        }
        System.out.println("\n\n運用埃拉托色篩選法求小于等于n的所有質(zhì)數(shù)");
        boolean[] isPrime = sieveOfEratosthenes(num);
        count=0;
        for (int i = 2; i <= num; i++) {
            if (isPrime[i]) {
                if (count % 10 == 0) {
                    System.out.println();
                }
                System.out.print(i + "\t");
                count++;
            }
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容