Leetcode952. 按公因数计算最大组件大小

题目链接

点我(^_^)

题目大意

Leetcode952. 按公因数计算最大组件大小_第1张图片
比如 nums = [4,6,15,35] 答案就是4,nums = [20,50,9,63] 答案就是2。

解题思路

我的思路是对 nums 数组中的每一个数进行质因数分解,那么对于每一个因数可以维护一个并查集,对于一个数字将其质因数分解后的所有因子可以看作是一个连通集合。这样在线维护并查集大小即可。素数筛+质因子分解+并查集,时间复杂度为 O(mlogn),m为数组大小,n为数字大小。

当然,也可以按照官方题解的做法,直接使用并查集维护,每一个数与其每一个因数都是一个连通组件,最后判断当前数字的父亲是谁,并对其集合大小进行更新即可。官方时间复杂度为 O(m n \sqrt{n} n )。

代码(C++)

我的代码

const int N = 1e5+5;
class Solution {
public:
    //核心:n只会被最小质因子筛掉
    int cnt = 0; //素数的个数
    int v[N]; //存每个数的最小质因子
    int prime[N]; //存素数
    int fa[N]; // 并查集父节点
    int size[N]; // 并查集大小

    void get_primes(int n){
        for(int i = 2;i <= n; ++i){
            if(v[i] == 0){
                v[i] = i;
                prime[++cnt] = i;
            }
            for(int j = 1 ; j <= cnt;++j){
                if(prime[j] > v[i] || i * prime[j] > n) break;
                v[prime[j] * i] = prime[j];
            }
        }
    }
    // void divide(int n) {
    //     while (v[n]) {
    //         printf("%d ", v[n]); // 在前
    //         n /= v[n]; //在后
    //     }
    // }
    int find(int x)
    {
        if(x == fa[x])
            return x;
        else
            return find(fa[x]);
    }
    int largestComponentSize(vector<int>& nums) {
        int ans = 1;
        get_primes(100000);
        for(int i=0; i<nums.size(); ++i)
        {
            int father = 0;
            while (v[nums[i]])
            {
                int now = v[nums[i]];
                if(father == 0)
                {
                    father = now;
                    if(fa[father] == 0)
                    {
                        fa[father] = father;
                        size[father] = 1;
                    }
                    else
                    {
                        size[find(father)] ++;
                        ans = max(ans, size[find(father)]);
                    }
                }
                else
                {
                    if(fa[now] == 0)
                    {
                        fa[now] = find(father);
                    }
                    else if(find(father) != find(now))
                    {
                        size[find(father)] += size[find(now)];
                        ans = max(size[find(father)], ans);
                        fa[find(now)] = find(father);
                    }
                }
                while (nums[i] % now == 0)
                    nums[i] /= now;
            }
        }
        return ans;
    }
};

官方代码

class UnionFind {
public:
    UnionFind(int n) {
        parent = vector<int>(n);
        rank = vector<int>(n);
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }

    void uni(int x, int y) {
        int rootx = find(x);
        int rooty = find(y);
        if (rootx != rooty) {
            if (rank[rootx] > rank[rooty]) {
                parent[rooty] = rootx;
            } else if (rank[rootx] < rank[rooty]) {
                parent[rootx] = rooty;
            } else {
                parent[rooty] = rootx;
                rank[rootx]++;
            }
        }
    }

    int find(int x) {
        if (parent[x] != x) {
            parent[x] = find(parent[x]);
        }
        return parent[x];
    }
private:
    vector<int> parent;
    vector<int> rank;
};

class Solution {
public:
    int largestComponentSize(vector<int>& nums) {
        int m = *max_element(nums.begin(), nums.end());
        UnionFind uf(m + 1);
        for (int num : nums) {
            for (int i = 2; i * i <= num; i++) {
                if (num % i == 0) {
                    uf.uni(num, i);
                    uf.uni(num, num / i);
                }
            }
        }
        vector<int> counts(m + 1);
        int ans = 0;
        for (int num : nums) {
            int root = uf.find(num);
            counts[root]++;
            ans = max(ans, counts[root]);
        }
        return ans;
    }
};

你可能感兴趣的:(力扣刷题笔记,leetcode,算法,c++)