Problem
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:
1 | Input: [4,6,15,35] |
Example 2:
1 | Input: [20,50,9,63] |
Example 3:
1 | Input: [2,3,6,7,4,12,21,39] |
Note:
1 <= A.length <= 20000
1 <= A[i] <= 100000
Analysis
题目给出了若干个数,然后定义两个数相连的条件是他们有大于1的公因子。之前也遇到过类似的动态连接问题,当时的解决方法是用并查集,这里也是一样的,但是用法有点不同。这里我们怎么去判断某个节点的类别呢?
因为是通过公因子来建立连接关系的,所以我们直接就用公因子作为某个数的类别。以15为例,它的公因子(1和本身除外)就是3、5。所以它就有两个类别。如果有相同的公因子,那么就把他们连接起来。构建完并查集后,我们遍历每个数字的父节点(类别),最后找到数量最多的那个类别,这个数量的就是连通分量的数量了。
Solution
这道题最本质的就是并查集的实现。用数组中最大的数作为最大的节点号码,然后初始化整个并查集。并查集的find
和union
操作都比较简单。然后就是遍历题目给出的数字,找到因子。这里先计算sqrt,可以减少遍历的次数。最后用map来统计。
Code
1 | class DSU { |
Summary
这道题是并查集很好的一个应用例子,之前的题目都是并查集的直接使用,这道题需要结合题目的特点,去调整并查集的使用,但是背后使用的本质还是连通性的维持。这道题的分析到这里,谢谢!