952. Largest Component Size by Common Factor

Given a non-empty array of unique positive integers A, consider the following graph:

  • There are A.length nodes, labelled A[0] to A[A.length - 1];
  • There is an edge between A[i] and A[j] if and only if A[i] and A[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. 1 <= A.length <= 20000
  2. 1 <= A[i] <= 100000

这道题给了一个非空正数数组A,现在将每个数字看作一个结点,定义两个结点相连的条件是两个数字共享一个大于1的因子,求最大的相连的结点个数。这道题看似像一个图的问题,其实跟图并没有太大的关系,本质上就是群组问题,这种归组类的问题,最典型的就是岛屿问题(例如 Number of Islands II),很适合使用联合查找 Union Find 来做,也叫并查集,LeetCode 中有很多道可以使用这个方法来做的题,比如 Friend CirclesGraph Valid TreeNumber of Connected Components in an Undirected Graph,和 Redundant Connection 等等。都是要用一个 root 数组,每个点开始初始化为不同的值,如果两个点属于相同的组,就将其中一个点的 root 值赋值为另一个点的位置,这样只要是相同组里的两点,通过 find 函数得到相同的值。这里也是一样,我们希望把所有至少共享一个大于2的因子的数字都放到一个群组中,那么初始化数组的大小就应该是数组A中最大的数字加1,因为数组序列是0开头的。先遍历一遍数组A,找出最大数字,然后建立 root 数组初始化为不同的群组。之后遍历数组A,对于每个数字,找出其所有大于2的因子,由于因子都是成对出现的,所以只需要从其平方根遍历到2即可,每当找到一对因子,分别将其跟原数组合并起来,注意在更新 root 数组的时候,对于每个数字都要调用 find 函数,这里希望将同一个群组的 root 值都更新为相同的值,这样方便后面统计每个群组中结点的个数。当所有的因子都合并完成了之后,下面进行查找操作,使用一个 HashMap 来建立群组祖先结点值和结点个数之间的映射。对于每个遍历到的数组,通过 find 函数查找祖先值,然后将其在 HashMap 中映射值自增1,然后用更新后的值来更新结果 res 即可,参见代码如下:

class Solution {
public:
    int largestComponentSize(vector<int>& A) {
        int n = 0, mx = 0, res = 0;
        unordered_map<int, int> m;
        for (int num : A) mx = max(mx, num);
        vector<int> root(mx + 1);
        for (int i = 1; i <= mx; ++i) root[i] = i;
        for (int num : A) {
            for (int d = sqrt(num); d >= 2; --d) {
                if (num % d == 0) {
                    root[find(root, num)] = root[find(root, d)];
                    root[find(root, num)] = root[find(root, num / d)];
                }
            }
        }
        for (int num : A) {
            res = max(res, ++m[find(root, num)]);
        }
        return res;
    }
    int find(vector<int>& root, int x) {
        return root[x] == x ? x : (root[x] = find(root, root[x]));
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/952

参考资料:

https://leetcode.com/problems/largest-component-size-by-common-factor/

https://leetcode.com/problems/largest-component-size-by-common-factor/discuss/202053/C%2B%2B-solutions-Easy-to-understandDSU

https://leetcode.com/problems/largest-component-size-by-common-factor/discuss/349437/Java-Simple-O(N*sqrt(W))-Union-Find-Solution

LeetCode All in One 题目讲解汇总(持续更新中…)


转载请注明来源于 Grandyang 的博客 (grandyang.com),欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 grandyang@qq.com

💰


微信打赏


Venmo 打赏

(欢迎加入博主的知识星球,博主将及时答疑解惑,并分享刷题经验与总结,试运营期间前五十位可享受半价优惠~)

×

Help us with donation