求素數(shù)個數(shù)

我最近在leetcode上擼了一個小算法膘螟,雖然已經(jīng)工作了五年成福,當看到每次代碼提交后排名的提升碾局,內(nèi)心依然很有成就感荆残。題目比較簡單,求小于n的素數(shù)個數(shù)净当,素數(shù)也叫質(zhì)數(shù)内斯,具有以下特點:

  • 正整數(shù)
  • 只能被1和本身整除
  • 1既不是素數(shù)也不是合數(shù),所以最小的素數(shù)是2

根據(jù)上面的特點像啼,我們還可以推斷出:

  • 除了2俘闯,其它的素數(shù)都是奇數(shù)

依據(jù)這一點,我們可以寫出下面的實現(xiàn):

class Solution {
    public int countPrimes(int n) {
        if (n < 3) {
            return 0;
        }
        int count = 1;// 2
        for (int i = 3; i < n; i += 2) {
            // 只判斷奇數(shù)是不是素數(shù)
            boolean isPrime = true;
            for (int j = 3; j * j <= i; j += 2) {
                // 奇數(shù)不可能被偶數(shù)整除忽冻,所以只試除奇數(shù)
                if (i % j == 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) {
                count++;
            }
        }
        return count;
    }
}

j * j <= i相當于j <= Math.sqrt(i)真朗,但速度會快一點,那為什么只需要判斷到√i呢僧诚,因為對于一個非素數(shù)(合數(shù))遮婶,其最小約數(shù)(除1外)必小于等于其平方根。

設(shè)k為最小約數(shù)
這個實現(xiàn)被Accept了湖笨,但時間復雜度較高旗扑,排名也很靠后。這個算法中慈省,判斷一個奇數(shù)i是不是素數(shù)臀防,是通過試除小于等于√i的奇數(shù)來實現(xiàn),這會有重復計算的場景边败,比如3和9袱衷,5和15,根據(jù)素數(shù)和合數(shù)的特點笑窜,可以推斷出任意一個合數(shù)都可以分解成幾個素數(shù)的乘機致燥,所以我們可以通過試除小于等于√i的素數(shù)來判斷i是不是素數(shù),素數(shù)相對于奇數(shù)怖侦,無疑減少了很多判斷次數(shù)篡悟。

class Solution {
    public int countPrimes(int n) {
        if (n < 3) {
            return 0;
        }
        int count = 0;
        int[] primes = new int[n / 2];
        for (int i = 3; i < n; i += 2) {
            // 只判斷奇數(shù)是不是素數(shù)
            boolean isPrime = true;
            for (int j = 0; j < count && primes[j] * primes[j] <= i; j++) {
                // 只試除素數(shù)
                if (i % primes[j] == 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime) {
                primes[count++] = i;
            }
        }
        return count + 1;// 2
    }
}

效果好了一些,但這個實現(xiàn)時間復雜度依然很高匾寝,比試除法更高效的是篩選法搬葬,篩選法的策略是將素數(shù)的倍數(shù)全部篩掉,剩下的就是素數(shù)了艳悔,下圖很生動的體現(xiàn)了篩選的過程:
埃拉托斯特尼篩法

篩選的過程是先篩掉非素數(shù)急凰,針對本文的題目,每篩掉一個,素數(shù)數(shù)量-1即可抡锈,上面說過素數(shù)的一個特點疾忍,除了2,其它的素數(shù)都是奇數(shù)床三,所以我們只需在奇數(shù)范圍內(nèi)篩選就可以了一罩。

class Solution {
    public int countPrimes(int n) {
        if (n < 3) {
            return 0;
        }
        int count = n / 2;// 篩掉一半偶數(shù)
        boolean[] notPrime = new boolean[n];
        for (int i = 3; i * i < n; i += 2) {// 只篩3≤i<√n奇數(shù)
            if (!notPrime[i]) {        
                // 篩掉素數(shù)的奇數(shù)倍數(shù)
                for (int j = i * i; j < n; j += 2 * i) {// 從i*i開始篩
                    if (!notPrime[j]) {
                        notPrime[j] = true;
                        count--;
                    }
                }
            }
        }
        return count;
    }
}
示例 3 5 7 9 11 13 15 17 19 21 23 25 27 29 備注
i=3 3 5 7 9 11 13 15 17 19 21 23 25 27 29 3->9,15,21,27
i=5 3 5 7 9 11 13 15 17 19 21 23 25 27 29 5->25

對于一個奇數(shù)i,會依次篩掉i*i,i(i+2),i(i+4),i(i+6)…i(i+2n)撇簿,那么為什么不篩3i,5i,7i…(i-4)i,(i-2)i呢聂渊,因為他們已經(jīng)被篩過了,當我們要篩掉奇數(shù)i的倍數(shù)時四瘫,那么i之前的奇數(shù)(i-2,i-4…7,5,3)的倍數(shù)((i-2)i,(i-4)i…7i,5i,3i)已經(jīng)被篩掉了汉嗽,這個算法的效果還不錯。

版權(quán)聲明
本博客所有的原創(chuàng)文章找蜜,作者皆保留版權(quán)饼暑。轉(zhuǎn)載必須包含本聲明,保持本文完整洗做,并以超鏈接形式注明作者高爽和本文原始地址:http://www.reibang.com/p/d6736b492720弓叛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市竭望,隨后出現(xiàn)的幾起案子邪码,更是在濱河造成了極大的恐慌,老刑警劉巖咬清,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闭专,死亡現(xiàn)場離奇詭異,居然都是意外死亡旧烧,警方通過查閱死者的電腦和手機影钉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掘剪,“玉大人平委,你說我怎么就攤上這事《崴” “怎么了廉赔?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長匾鸥。 經(jīng)常有香客問我蜡塌,道長,這世上最難降的妖魔是什么勿负? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任馏艾,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘琅摩。我一直安慰自己铁孵,他們只是感情好,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布房资。 她就那樣靜靜地躺著蜕劝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪志膀。 梳的紋絲不亂的頭發(fā)上熙宇,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天鳖擒,我揣著相機與錄音溉浙,去河邊找鬼。 笑死蒋荚,一個胖子當著我的面吹牛戳稽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播期升,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼惊奇,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了播赁?” 一聲冷哼從身側(cè)響起颂郎,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎容为,沒想到半個月后乓序,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡坎背,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年替劈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片得滤。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡陨献,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出懂更,到底是詐尸還是另有隱情眨业,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布沮协,位于F島的核電站龄捡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏皂股。R本人自食惡果不足惜墅茉,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧就斤,春花似錦悍募、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绷旗,卻和暖如春喜鼓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衔肢。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工庄岖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人角骤。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓隅忿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親邦尊。 傳聞我的和親對象是個殘疾皇子背桐,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗。 張土汪:刷leetcod...
    土汪閱讀 12,744評論 0 33
  • 自然方程是揭示中醫(yī)藥學基礎(chǔ)理論的數(shù)學結(jié)構(gòu)框架 摘要:本人在素數(shù)問題的幾十年研究中蝉揍,找到了三種素數(shù)生成函數(shù)方法链峭,展示...
    星辰閱讀 1,194評論 1 5
  • 我希望自己的每個腳印都鏗鏘有力,收到的每一聲問候都發(fā)自內(nèi)心又沾。 是的弊仪,我和每一個同齡人一樣,渴望一個溫暖的懷抱捍掺,一段...
    素色墨染閱讀 214評論 0 3
  • (我用的是Xcode8.3.1)今天在用xib拖一個cell的時候突然給我報兩個錯誤 可神奇的是可以運行,雖然不影...
    傅hc閱讀 2,181評論 7 3
  • 任何東西都是脆弱的吧撼短? 昨晚不知道吃東西的哪一環(huán)節(jié)出了差錯,凌晨肚子疼的厲害挺勿。清晰記得那種感覺曲横,冷汗一陣一陣,臉上...
    33bdc3c72501閱讀 245評論 0 0