↓快轉到主要內容
  1. LeetCode/

LeetCode 204: Count Primes

·1 分鐘· ·
LeetCode Medium Array Math Enumeration Number-Theory
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: medium 第一次嘗試:2022-11-11

  • 提交紀錄:Output Limit Exceeded → Time Limit Exceeded ×4 → Runtime Error ×2 → Accepted → Wrong Answer → Accepted ×2

解題思路
#

埃氏篩(Number Theory 模板三):is_prime 初始都是 True,從 2 開始,只有還是質數的 p 才去劃掉倍數,而且從 p² 開始(更小的倍數已經被更小的質因數劃過了);p 只要跑到 √n。Python 用切片賦值 is_prime[p*p::p] = ... 比內層迴圈快很多。

我的嘗試
#

這題提交了 11 次:

  • 2022-11-11 第一版留了 print(Output Limit Exceeded)。之後幾版雖然有篩,但條件寫成 if num:,每個數都會去劃倍數,不管它是不是質數,外層也跑到 n,TLE 了四次。
  • 2022-11-17 改成外層到 √n、用切片賦值,先是變數打錯(NameError)、n < 2 時 prime[1] 超出範圍(IndexError),補上特例就 AC 了。
  • 2026 年重寫成線性篩,第一次把條件寫成 if is_composite[i],意思剛好相反,一個質數都沒加進去:n = 3 回傳 0,答案 1。

正確解法
#

class Solution:
    def countPrimes(self, n: int) -> int:
        if n < 3:
            return 0
        is_prime = [True] * n
        is_prime[0] = is_prime[1] = False
        for p in range(2, int(n ** 0.5) + 1):
            if is_prime[p]:
                is_prime[p * p::p] = [False] * len(range(p * p, n, p))
        return sum(is_prime)

複雜度
#

時間 O(n log log n),空間 O(n)。

要特別避免的錯誤
#

  • 只用質數去篩:合數的倍數早就被它的質因數劃掉了。
  • 外層到 √n 就夠。
  • n < 2 時陣列太短,is_prime[1] 會超出範圍。
  • 線性篩的條件是「不是合數就加入質數表」,寫反了一個質數都找不到。

面試口說整理
#

我用埃氏篩,從 2 到根號 n,遇到還是質數的 p 就從 p 平方開始把它的倍數劃掉,最後數還剩幾個 True。時間 O(n log log n)。

相關文章

LeetCode 189: Rotate Array
·1 分鐘
LeetCode Medium Array Math Two-Pointers
LeetCode 189 解題筆記:先 k %= n,再用三次反轉:整個反轉、前 k 個反轉、後 n - k 個反轉;O(1) 額外空間
LeetCode 48: Rotate Image
·1 分鐘
LeetCode Medium Array Math Matrix
LeetCode 48 解題筆記:順時針轉 90 度 = 先轉置再把每一列左右反轉,兩步都可以原地做
LeetCode 973: K Closest Points to Origin
·1 分鐘
LeetCode Medium Array Math Divide-and-Conquer Geometry
LeetCode 973 解題筆記:跟 Top-K 一樣,用大小為 k 的 max-heap(存負的距離)保留最近的 k 個點
LeetCode 134: Gas Station
·1 分鐘
LeetCode Medium Array Greedy
LeetCode 134 解題筆記:總油量不夠就不可能;否則從左掃,油箱變負就把起點移到下一站
LeetCode 162: Find Peak Element
·1 分鐘
LeetCode Medium Array Binary-Search
LeetCode 162 解題筆記:nums[mid] < nums[mid + 1] 代表右邊一定有山峰(一路上升最後也會碰到邊界),否則左邊(含 mid)一定有
LeetCode 106: Construct Binary Tree from Inorder and Postorder Traversal
·1 分鐘
LeetCode Medium Array Hash-Table Divide-and-Conquer Tree
LeetCode 106 解題筆記:後序的最後一個是根;從後序尾巴往前取根時,要先建右子樹再建左子樹