目录

0952:按公因数计算最大组件大小(2272 分)

力扣第 113 场周赛第 4 题

题目

给定一个由不同正整数的组成的非空数组 nums ,考虑下面的图:

  • nums.length 个节点,按从 nums[0]nums[nums.length - 1] 标记;
  • 只有当 nums[i]nums[j] 共用一个大于 1 的公因数时,nums[i]nums[j]之间才有一条边。

返回 图中最大连通组件的大小

示例 1:

输入:nums = [4,6,15,35]
输出:4

示例 2:

输入:nums = [20,50,9,63]
输出:2

示例 3:

输入:nums = [2,3,6,7,4,12,21,39]
输出:8

提示:

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 105
  • nums 中所有值都 不同

相似问题:

分析

#1

  • 典型的并查集,问题在于不能二重遍历
  • 可以考虑直接遍历公因数 x,遍历 x 的倍数 y,如果 y 在 nums 中,就和 x 相连
  • 这样总时间是调和级数,趋于 O(n logn)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution:
    def largestComponentSize(self, nums: List[int]) -> int:
        def find(x):
            if f[x] != x:
                f[x] = find(f[x])
            return f[x]

        def union(x,y):
            f[find(x)] = find(y)

        ma = max(nums)+1
        f = list(range(ma))
        vis = set(nums)
        for x in range(2,ma):
            for y in range(x,ma,x):
                if y in vis:
                    union(x,y)
        return max(Counter(find(x) for x in nums).values())

2122 ms

#2

  • 还可以只枚举质数作为公因数 p
  • 质数可以用埃氏筛预处理

解答

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
M = 10**5+1
f = [1]*M
for i in range(2,isqrt(M)+1):
    if f[i]:
        f[i*i:M:i] = [0] * ((M-1-i*i)//i+1)
primes = [i for i in range(2,M) if f[i]]

class Solution:
    def largestComponentSize(self, nums: List[int]) -> int:
        def find(x):
            if f[x] != x:
                f[x] = find(f[x])
            return f[x]

        def union(x,y):
            f[find(x)] = find(y)

        ma = max(nums)+1
        f = list(range(ma))
        vis = set(nums)
        for x in primes:
            if x>ma:
                break
            for y in range(x,ma,x):
                if y in vis:
                    union(x,y)
        return max(Counter(find(x) for x in nums).values())

608 ms