(演算法)求1到1億間的質數或素數

weixin_34126215發表於2015-08-02

題目:

求1到1億間的質數或素數

思路:

什麼是質數?

質數(prime number)又稱素數,有無限個。一個大於1的自然數,除了1和它本身外,不能被其他自然數(質數)整除,換句話說就是該數除了1和它本身以外不再有其他的因數;否則稱為合數。(來自百度百科)

方法1:

遍歷1到1億間的所有數,然後逐個判斷是否為質數;

如何判斷一個數為質數?根據質數的定義,判斷該數是否能被1和它本身之外的數整除,如果是,則不是質數,否則為質數;一般只需判斷是否能被2到sqrt(num)的所有數整數。

方法2:

上述方法時間複雜度較高,對於1億個數而言,不太實際。

其實當我們遍歷到某個數(如:n)的時候,所有n的倍數的數字均不為質數,後續我們無需對這個數再做判斷的操作,這樣可以減少很多不必要的計算;

而且,我們可以從逆向思維來考慮,出了各個n的倍數的數字之外,其他的就是質數,於是少了判斷是否為質數的過程。

現在需要做的就是將這些提前判斷為非質數的數字儲存起來,可以通過一個bool陣列,如果某個數字為非質數,則在對應下標的陣列位置做標誌,以供後續判斷。

時間複雜度:O(n),空間複雜度:O(n)

注意:

這裡處理的是一億個數字,因此需考慮機器的記憶體問題,32位機器的int表示範圍為0~2^32-1即4394967295,能表示一億,一億個int需要的記憶體為400M。

(下面的程式碼建立在記憶體足夠的情況下)

程式碼:

#include <iostream>
#include <vector>

using namespace std;

const unsigned int MAX_NUM=100;

void Prime(vector<bool> &numbers,vector<int> &primes){
    for(unsigned int i=2;i<=MAX_NUM;i++){
        if(numbers[i]==false){
            primes.push_back(i);
            // multiple of i
            for(unsigned int j=i;j<=MAX_NUM;j+=i)
                numbers[j]=true;
        }
    }
}


int main()
{
    vector<bool> numbers(MAX_NUM,false);
    vector<int> primes;

    Prime(numbers,primes);

    vector<int>::iterator it=primes.begin();
    for(;it!=primes.end();it++){
        cout<<*it<<endl;
    }

    return 0;
}

相關文章