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

LeetCode 952: Largest Component Size by Common Factor

·2 分鐘· ·
LeetCode Hard Math Number-Theory Union-Find Hash-Table Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2025-05-10

  • 提交紀錄:TLE ×2 → AC(2025-05-17)→ TLE → AC ×2(2026-10-12 重寫)

解題思路
#

兩個數有大於 1 的公因數 ⇔ 有共同的質因數。

  • 兩兩算 GCD 是 O(n^2 log M),n = 2 × 10^4 會超時。
  • 改成對每個數分解質因數(試除到 √x),記錄每個質因數第一次出現的 index owner[p]。之後再遇到同一個質因數,就跟 owner[p] 合併。

最後數每一組的大小,取最大值。

我的嘗試
#

時間版本問題
2025-05兩次 TLE兩兩算 GCD,O(n^2)
2025-05AC改成依質因數分組,每組相鄰的 index 合併
2026-10TLE重寫時又回到兩兩算 GCD
2026-10AC(3.9 秒)改成 owner[p],但 find 寫成 return find(parent[a]),沒有存回 parent[a],等於沒有路徑壓縮
2026-10AC(1.3 秒)補上路徑壓縮

正確解法
#

class Solution:
    def largestComponentSize(self, nums: List[int]) -> int:
        n = len(nums)
        parent = list(range(n))

        def find(a: int) -> int:
            if parent[a] != a:
                parent[a] = find(parent[a])        # 路徑壓縮:存回去
            return parent[a]

        def union(a: int, b: int) -> None:
            ra, rb = find(a), find(b)
            if ra != rb:
                parent[ra] = rb

        owner = {}                                 # 質因數 -> 第一個擁有它的 index

        def link(i: int, p: int) -> None:
            if p in owner:
                union(i, owner[p])
            else:
                owner[p] = i

        for i, x in enumerate(nums):
            p = 2
            while p * p <= x:
                if x % p == 0:
                    link(i, p)
                    while x % p == 0:
                        x //= p
                p += 1
            if x > 1:
                link(i, x)                         # 剩下的大質因數

        return max(Counter(find(i) for i in range(n)).values())

複雜度
#

時間 O(n √M)(試除),M 是最大值;用 SPF 篩可以降到 O(M + n log M)。空間 O(n + 質因數數量)。

要特別避免的錯誤
#

  • 兩兩算 GCD:O(n^2)。
  • find 沒有把結果存回去:等於沒有路徑壓縮。
  • 試除完剩下的 x > 1 也是質因數。

面試口說整理
#

有共同因數就等於有共同的質因數,所以我不兩兩算 GCD,而是把每個數分解質因數,記下每個質因數第一次出現的 index,之後遇到同一個質因數就用 Union-Find 合併。最後數每一組的大小。時間 O(n √M)。

相關文章

LeetCode 3518: Smallest Palindromic Rearrangement II
·2 分鐘
LeetCode Hard Math Combinatorics Counting Hash-Table String
LeetCode 3518 解題筆記:回文由左半邊決定,變成「多重集合的第 k 個排列」;逐位試每個字元,用排列數判斷第 k 個落在哪個分支,排列數可以 O(1) 更新
LeetCode 1814: Count Nice Pairs in an Array
·1 分鐘
LeetCode Medium Array Hash-Table Math Counting
LeetCode 1814 解題筆記:把條件移項成 nums[i] - rev(nums[i]) == nums[j] - rev(nums[j]),按這個值分組數 pair,記得取模
LeetCode 204: Count Primes
·1 分鐘
LeetCode Medium Array Math Enumeration Number-Theory
LeetCode 204 解題筆記:埃氏篩,只用質數 p 從 p² 開始把倍數劃掉,外層只要到 √n
LeetCode 128: Longest Consecutive Sequence
·1 分鐘
LeetCode Medium Array Hash-Table Union-Find
LeetCode 128 解題筆記:放進 set,只從「x - 1 不在 set 裡」的數開始往上數,每個數最多被看兩次,O(n)
LeetCode 914: X of a Kind in a Deck of Cards
·1 分鐘
LeetCode Easy Array Hash-Table Math Counting
LeetCode 914 解題筆記:每種卡片的張數都要能被同一個 X >= 2 整除,也就是所有張數的 GCD >= 2
LeetCode 268: Missing Number
·1 分鐘
LeetCode Easy Array Hash-Table Math Binary-Search
LeetCode 268 解題筆記:0 到 n 的總和減掉陣列總和就是缺的那個;缺的可能是 0