题解采用了素数筛法结合并查集的方法来解决问题。首先,使用埃拉托斯特尼筛法预先计算出所有小于等于100000的素数,并为每个数标记它的素数因子。然后,对于每个输入数字,通过它的素数因子来定义它在图中的节点。如果两个数有共同的素数因子,它们在图中就是相连的。这样,问题转化为了找出具有共同素数因子的最大连通组件。使用并查集来处理节点的连接和组件的合并。最后,遍历输入数组,对每个数的素数因子进行并查集合并操作,最终通过计数并查集根的频率来确定最大的连通组件大小。
时间复杂度: O(n log log n + m log n)
空间复杂度: O(n + m)
N = 10 ** 5 + 1
primes = []
is_prime = [True] * N
decompose = [[] for _ in range(N)]
for i in range(2, N):
if not is_prime[i]:
continue
primes.append(i)
decompose[i].append(i)
for j in range(i*2, N, i):
is_prime[j] = False
decompose[j].append(i)
d = {p: i for i, p in enumerate(primes, 1)}
d[1] = 0
decompose[1].append(1)
class UnionSet:
__slots__ = ("arr", "rank")
def __init__(self, n):
self.arr = list(range(n))
self.rank = [0] * n
def find(self, a):
_arr = self.arr
if _arr[a] != a:
_arr[a] = self.find(_arr[a])
return _arr[a]
def link(self, a, b):
if (pa := self.find(a)) == (pb := self.find(b)):
return
_rank = self.rank
if _rank[pa] < _rank[pb]:
self.arr[pa] = pb
elif _rank[pa] > _rank[pb]:
self.arr[pb] = pa
else:
self.arr[pa] = pb
_rank[pb] += 1
class Solution:
def largestComponentSize(self, nums: List[int]) -> int:
us = UnionSet(bisect_right(primes, max(nums)) + 1)
for facs in map(decompose.__getitem__, nums):
for a, b in pairwise(facs):
us.link(d[a], d[b])
return max(
Counter(
us.find(d[facs[0]])
for facs in map(decompose.__getitem__, nums)
).values()
)