1. 程式人生 > 實用技巧 >每日一題20201203(204. 計數質數)

每日一題20201203(204. 計數質數)

204. 計數質數

思路

  • 列舉

    一般咱們用來判斷一個數比如說23是否是質數,我們可以用23除以[2, 23)裡面的數字,一旦有數字大於1,該數字肯定就不是質數。

    但是每次除以那麼多數字,其實可以簡化。

    想想一下,判斷x是否是y的因數(也就是x是否能被y整除)

    如果x是y的因素,那麼y ÷ x肯定也是y的因數,所以其實只要計算[2, min(y/x, y)]是否能被y整除就行。

    那麼什麼時候y/x最小呢

引用一下題解,感覺比我解釋的好:

但是此方法會超時


// 超時警告
func isPrime(x int) bool {
    for i := 2; i*i <= x; i++ {
        if x%i == 0 {
            return false
        }
    }
    return true
}

func countPrimes(n int) (cnt int) {
    for i := 2; i < n; i++ {
        if isPrime(i) {
            cnt++
        }
    }
    return
}
  • 埃氏篩

    簡單的說就是,如果x是質數,那麼2x 3x 4x....這些一定不是質數

    那麼從2開始我們就可以找出2的2倍,3倍,排除這些非質數,一直遍歷,看數組裡還有哪些質數,數量+1,返回總數即可

    所以可以寫出如下程式碼:

func countPrimes(n int) (cnt int) {
    // 建立一個bool陣列,裡面存放第N個數是否是質數
    // 初始化,使得每個數都是質數
    isPrime := make([]bool, n)
    for i := range isPrime {
        isPrime[i] = true
    }
    // 從2開始 2是質數,把數組裡2的倍數都刷為素數
    for i := 2; i < n; i++ {
        if isPrime[i] {
            cnt++
            for j := 2 * i; j < n; j += i {
                isPrime[j] = false
            }
        }
    }
    return
}

class Solution:
    def countPrimes(self, n: int) -> int:
        ans = 0
        result = [True for i in range(n)]
        for i in range(2, n):
            if result[i]:
                ans += 1
            j = 2 * i
            while j < n:
                result[j] = False
                j += i
        return ans