前言
最近閒來無事,刷刷題,碰到這樣一個題目:
需求:要求實現一個判斷素數的簡單函數
相關信息:素數就是隻能被1和自身整除的正整數。注意:1不是素數,2是素數。
輸入:任意整數
輸出:1——素數;0——非素數.
第一反應是將大於等於2的輸入整數循環除以每個小於自身且大於1的整數,若餘數爲0,則爲非素數。
再一想,這樣做速度實在太慢,時間複雜度爲。故在網上水了一波,看看到底有沒有更快速的算法。
解決方案
方案1
方案1,就是上述方法,代碼如下:
int prime(int p)
{
if(p<=1)
{
return 0;
}
for(int i=2;i<p;i++)
{
if(p%i==0)
{
return 0;
}
}
return 1;
}
方案2
方案2是方案1的改進方案,該方案基於以下客觀事實:一個數若可以進行因數分解,那麼分解時得到的兩個數一定是一個小於等於sqrt(n),一個大於等於sqrt(n),據此,上述代碼中並不需要遍歷到n-1,遍歷到sqrt(n)即可,因爲若sqrt(n)左側找不到約數,那麼右側也一定找不到約數。
int prime(int p)
{
if(p<=1)
{
return 0;
}
for(int i=2;i<int(sqrt(p))+1;i++)
{
if(p%i==0)
{
return 0;
}
}
return 1;
}
上述算法時間複雜度爲.
方案3(最優算法)
和方案2一樣,首先素數有這樣一個規律:大於等於5的質數一定和6的倍數相鄰。例如5和7,11和13等。
證明過程如下:
因此,我們將所有輸入的大於等於5的數據以上述方式表示,將其除以6,若餘數不爲1,或者5,則直接證明其不是素數,剩下的進行判斷:
int prime(int p)
{
if (p == 2 || p == 3)
{
return 1;
}
if (p % 6 != 1 && p % 6 != 5)
{
return 0;
}
for (int i = 5; i <= floor(sqrt(p)); i += 6)
{
if (p%i == 0 || p % (i + 2) == 0)
{
return 0;
}
}
return 1;
}
總結
算法3能極大降低運算量,提升運算速度。小小的問題,大大的智慧啊,感謝大神們,雖然我不知道是誰。