zoukankan      html  css  js  c++  java
  • [LeetCode] 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 题目讲解汇总(持续更新中...)

  • 相关阅读:
    jsp 页面获取当前路径
    html5 页面音频
    微信关于网页授权access_token和普通access_token的区别
    Texlive source
    vscode 快捷键
    vscode setting
    vscode extension 插件管理
    what
    linux manual
    java tool type
  • 原文地址:https://www.cnblogs.com/grandyang/p/13253468.html
Copyright © 2011-2022 走看看