我最近在leetcode上擼了乙個小演算法,雖然已經工作了五年,當看到每次**提交後排名的提公升,內心依然很有成就感。題目比較簡單,求小於n的素數個數,素數也叫質數,具有以下特點:
根據上面的特點,我們還可以推斷出:
依據這一點,我們可以寫出下面的實現:
class
solution
intcount = 1;// 2
for (int i = 3; i < n; i += 2)
}if (isprime)
}return
count;}}
j * j <= i
相當於j <= math.sqrt(i)
,但速度會快一點,那為什麼只需要判斷到√i呢,因為對於乙個非素數(合數),其最小約數(除1外)必小於等於其平方根。
這個實現被accept了,但時間複雜度較高,排名也很靠後。這個演算法中,判斷乙個奇數i是不是素數,是通過試除小於等於√i的奇數來實現,這會有重複計算的場景,比如3和9,5和15,根據素數和合數的特點,可以推斷出任意乙個合數都可以分解成幾個素數的乘機,所以我們可以通過試除小於等於√i的素數來判斷i是不是素數,素數相對於奇數,無疑減少了很多判斷次數。
class
solution
intcount = 0;
int primes = new
int[n / 2];
for (int i = 3; i < n; i += 2)
}if (isprime)
}return
count + 1;// 2}}
效果好了一些,但這個實現時間複雜度依然很高,比試除法更高效的是篩選法,篩選法的策略是將素數的倍數全部篩掉,剩下的就是素數了,下圖很生動的體現了篩選的過程:
篩選的過程是先篩掉非素數,針對本文的題目,每篩掉乙個,素數數量-1即可,上面說過素數的乙個特點,除了2,其它的素數都是奇數,所以我們只需在奇數範圍內篩選就可以了。
class
solution
intcount = n / 2;// 篩掉一半偶數
boolean notprime = new
boolean[n];
for (int i = 3; i * i < n; i += 2) }}
}return
count;}}
示例35
791113
1517
1921
2325
2729
備註i=3
3579
1113
1517
1921
2325
2729
3->9,15,21,27
i=53
57911
1315
1719
2123
2527
295->25
對於乙個奇數i,會依次篩掉i*i,i(i+2),i(i+4),i(i+6)…i(i+2n),那麼為什麼不篩3i,5i,7i…(i-4)i,(i-2)i呢,因為他們已經被篩過了,當我們要篩掉奇數i的倍數時,那麼i之前的奇數(i-2,i-4…7,5,3)的倍數((i-2)i,(i-4)i…7i,5i,3i)已經被篩掉了,這個演算法的效果還不錯。
MPI求素數個數
附上另乙個呼叫函式後針對乙個輸入正確 include stdafx.h include mpi.h include stdio.h include string.h include math.h int isprime int n return flag int main int argc,char...
48 求質數 素數 個數
48 求質數 素數 個數 問題描述 求出所有的大於等於n小於等於m的質數,統計其數目。n m 輸入說明 你的程式需要從標準輸入裝置 通常為鍵盤 中讀入多組測試資料。每組一行,每行包含兩個整數n m n m都不大於20000 兩組資料之間沒有多餘的空行。在行首和行尾沒有多餘的空格。輸出說明 對每組測試...
篩素數,求區間內素數個數
問題 1525 藍橋杯 演算法提高vip 找素數 時間限制 1sec 記憶體限制 128mb 提交 1179 解決 133 題目描述 給定區間 l,r 請計算區間中素數的個數。資料規模和約定 2 l r 2147483647 r l 1000000 輸入兩個數l和r。輸出一行,區間中素數的個數。樣例...