leetcode——Count Primes

題目

Description:

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

方法

對於這道題,最簡單最直觀的方法往往是:對n以下的每一個數字進行判斷從而求出個數。而在對每個數字(比如x)判斷的時候,又是暴力驗證的思想,即從2開始一直到sqrt(x)進行相除判斷是否整除。更有甚者直接從2到x/2或x進行判斷。這樣的效率是極其低下的,這篇文章如果講的是以上的東西,那就失去意義了。下面來講一個最爲高效的做法,並不難,關鍵在於理解。

先來看圖:
這裏寫圖片描述

我們從一個有着n個數字的一維數組開始,先看第一個數字2.我們知道所有因數爲2的數字(除了2本身)都不是質數,所以我們把他們標記爲非質數;然後看下一個數字,3.同樣道理,所有因數爲3的數字也都不是質數,比如 3 × 2 = 6, 3 × 3 = 9, … ,這些一定不是質數,所以我們也可以把他們標記出來。現在來看4,這是一個已經標記出來的數字。這說明什麼?難道還需要把所有因數有4的數字去掉嗎?

4並不是質數,因爲它能被2整除,這也告訴我們所有以4爲因數的數字都能被2整除,而它們已經被剔除掉了(在討論2的時候)。所以我們可以跳過4去考慮下一個數字:5。現在,所有因數爲5的數字,比如5 × 2 = 10, 5 × 3 = 15, 5 × 4 = 20, 5 × 5 = 25, … 都能夠被剔除掉了。不過這裏有一個小的優化:我們並不需要從5x2開始,我們僅僅需要從5 x 5開始。原因如下:

5 × 2 = 10 早在討論2的時候就已經被排除掉了,同理,5 x 3 早在討論3的時候被排除掉了。因此,既然我們一路從2上來,那麼任何比當前數字小的因數(當前爲5)都已經做過排除處理,因此我們不需要再討論它們;我們所要討論的是從當前數字的平方開始一直到最末的這些數。如果當前數字爲p,p2爲pxp,那麼我們要討論的就是:p2,p2 + p, p2 + 2p, … 而這個循環的終止條件就是,j < n (其中,j = p2 + m*p).

當循環結束的時候,那些沒被標記過的數字就是質數。

代碼

public int countPrimes(int n) {
        boolean[] isPrime = new boolean[n+1];
        for(int i=1;i<=n;i++){
            isPrime[i] = true;
        }

        for(int i=2;i*i<n;i++){
            if(!isPrime[i]){
                continue;
            }
            for(int j=i*i;j<n;j+=i){
                isPrime[j] = false;
            }
        }

        int count = 0;
        for(int i=2;i<n;i++){
            if(isPrime[i])
                count++;
        }
        return count;
    }
發佈了111 篇原創文章 · 獲贊 9 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章