力扣每日一题0730-952. 按公因数计算最大组件大小

73 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情

给定一个由不同正整数的组成的非空数组 nums ,考虑下面的图

  • 有 nums.length 个节点,按从 nums[0] 到 nums[nums.length - 1] 标记;
  • 只有当 nums[i] 和 nums[j] 共用一个大于 1 的公因数时,nums[i] 和 nums[j]之间才有一条边。

返回 图中最大连通组件的大小

示例 1:

image.png

输入:nums = [4,6,15,35]
输出:4

示例 2:

image.png

输入:nums = [20,50,9,63]
输出:2

示例 3:

image.png

输入:nums = [2,3,6,7,4,12,21,39]
输出:8

并查集

为了得到数组 nums\textit{nums} 中的每个数和哪些数属于同一个组件,需要得到数组 nums\textit{nums} 中的最大值 mm,对于每个不超过 mm 的正整数 num\textit{num} 计算 num\textit{num} 和哪些数属于同一个组件。对于范围 [2,num][2, \sqrt{\textit{num}}] 内的每个正整数 ii,如果 iinum\textit{num} 的因数,则 num\textit{num}iinumi\dfrac{\textit{num}}{i} 都属于同一个组件。

可以使用并查集实现组件的计算。初始时,每个数分别属于不同的组件。如果两个正整数满足其中一个正整数是另一个正整数的因数,则这两个正整数属于同一个组件,将这两个正整数的组件合并。

当所有不超过 mm 的正整数都完成合并操作之后。遍历数组 nums\textit{nums},对于每个数得到其所在的组件并更新该组件的大小,遍历结束之后即可得到最大组件的大小。

var largestComponentSize = function(nums) {
    const m = _.max(nums);;
    const uf = new UnionFind(m + 1);
    for (const num of nums) {
        for (let i = 2; i * i <= num; i++) {
            if (num % i === 0) {
                uf.union(num, i);
                uf.union(num, Math.floor(num / i));
            }
        }
    }
    const counts = new Array(m + 1).fill(0);
    let ans = 0;
    for (let num of nums) {
        const root = uf.find(num);
        counts[root]++;
        ans = Math.max(ans, counts[root]);
    }
    return ans;
};

class UnionFind {
    constructor(n) {
        this.parent = new Array(n).fill(0).map((_, i) => i);
        this.rank = new Array(n).fill(0);
    }

    union(x, y) {
        let rootx = this.find(x);
        let rooty = this.find(y);
        if (rootx !== rooty) {
            if (this.rank[rootx] > this.rank[rooty]) {
                this.parent[rooty] = rootx;
            } else if (this.rank[rootx] < this.rank[rooty]) {
                this.parent[rootx] = rooty;
            } else {
                this.parent[rooty] = rootx;
                this.rank[rootx]++;
            }
        }
    }

    find(x) {
        if (this.parent[x] !== x) {
            this.parent[x] = this.find(this.parent[x]);
        }
        return this.parent[x];
    }
}