Given a non-empty array of unique positive integers A
, consider the following graph:
- There are
A.length
nodes, labelledA[0]
toA[A.length - 1];
- There is an edge between
A[i]
andA[j]
if and only ifA[i]
andA[j]
share a common factor greater than 1.
Return the size of the largest connected component in the graph.
Example 1:
Input: [4,6,15,35] Output: 4
Example 2:
Input: [20,50,9,63] Output: 2
Example 3:
Input: [2,3,6,7,4,12,21,39] Output: 8
Note:
1 <= A.length <= 20000
1 <= A[i] <= 100000
思路:一开始想求出数组每个数之间是不是联通的,然后跑BFS,TLE
class Solution:
def largestComponentSize(self, A):
"""
:type A: List[int]
:rtype: int
"""
n=len(A)
A.sort()
# adj=[[False for _ in range(n)] for _ in range(n)]
adj=[set() for _ in range(n)]
for i in range(n):
for j in range(i+1, n):
a,b=A[i],A[j]
while b%a: a,b=b%a,a
if a>1:
# adj[i][j]=True
adj[i].add(j)
adj[j].add(i)
vis=[False]*n
ma=0
for i in range(n):
if vis[i]: continue
vis[i]=True
q=[i]
cnt=1
while q:
s=q.pop()
for t in adj[s]:
if vis[t]: continue
q.append(t)
vis[t]=True
cnt+=1
ma=max(ma,cnt)
return ma
s=Solution()
print(s.largestComponentSize([4,6,15,35]))
print(s.largestComponentSize([20,50,9,63]))
print(s.largestComponentSize([2,3,6,7,4,12,21,39]))
#print(s.largestComponentSize(A))
然后就想,循环遍历数组的每个index pair似乎太慢,就是在bfs里面每次都是cnt+=1。
其实我们可以把所有的素数求出来,包含每个素数的数可以看成一个group,这样每次union联通在一起的素数,每次累加就是约数里含有该素数的所有数(也就是这个group里面的所有数)
那怎么判断哪些素数应该union起来呢,就是对每个数做素数分解,然后这个数对应的这些素数的group都应该union起来。
这里其实是角度的变换,之前是union数组A中不同index的数,现在是union素数group;之前union的判据是数组A中是不是有共同约数(外部计算),现在是数组A中每个数的素数约数两两之间就可以union(内部计算)
from collections import Counter
class Solution:
def largestComponentSize(self, A):
"""
:type A: List[int]
:rtype: int
"""
primes = []
for t in A:
prime = []
p = 2
while p*p<=t:
if t%p==0:
while t%p==0:
t/=p
prime.append(p)
p+=1
if t>1 or not prime: prime.append(t) # t is a prime
primes.append(prime)
all_primes = list({p for prime in primes for p in prime})
prime2group= {t:i for i,t in enumerate(all_primes)}
# build adj first and run BFS
# or just run union-find
fa = list(range(len(all_primes)))
def find(i):
if fa[i]!=i: fa[i]=find(fa[i])
return fa[i]
def union(i,j):
ii,jj=find(i),find(j)
fa[ii]=jj
for prime in primes:
for p in prime:
union(prime2group[prime[0]], prime2group[p])
count = Counter(find(prime2group[prime[0]]) for prime in primes)
return max(count.values())
s=Solution()
print(s.largestComponentSize([4,6,15,35]))
print(s.largestComponentSize([20,50,9,63]))
print(s.largestComponentSize([2,3,6,7,4,12,21,39]))
#print(s.largestComponentSize(A))
union-find也可以替换为BFS,只要预先求出哪些group要union就可以了