携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情
给定一个由不同正整数的组成的非空数组 nums ,考虑下面的图:
- 有
nums.length个节点,按从nums[0]到nums[nums.length - 1]标记; - 只有当
nums[i]和nums[j]共用一个大于 1 的公因数时,nums[i]和nums[j]之间才有一条边。
返回 图中最大连通组件的大小 。
示例 1:
输入: nums = [4,6,15,35]
输出: 4
示例 2:
输入: nums = [20,50,9,63]
输出: 2
示例 3:
输入: nums = [2,3,6,7,4,12,21,39]
输出: 8
提示:
1 <= nums.length <= 2 * 10^41 <= nums[i] <= 10^5nums中所有值都 不同
解题
/**
* @param {number[]} nums
* @return {number}
*/
var largestComponentSize = function (nums) {
const len = nums.length;
if (len === 1) return 1;
const getPrimeFactor = (n) => {
const res = [];
if ((n & 1) === 0) {
res.push(2);
while ((n & 1) === 0) {
n = n >> 1;
}
}
for (let i = 3; i * i <= n; i += 2) {
if (n % i === 0) {
res.push(i);
while (n % i === 0) {
n = n / i;
}
}
}
if (n > 1) {
res.push(n);
}
return res;
};
const uf = new UnionFind();
let maxSize = 0;
for (let i = 0; i < len; i++) {
let primes = getPrimeFactor(nums[i]);
for (let j = 0; j < primes.length; j++) {
uf.union(primes[j], nums[i]);
}
}
const sizeMap = new Map();
for (let i = 0; i < len; i++) {
const root = uf.find(nums[i]);
const size = (sizeMap.get(root) ?? 0) + 1;
sizeMap.set(root, size);
maxSize = Math.max(maxSize, size);
}
return maxSize;
};
class UnionFind {
constructor() {
this.parents = new Map();
}
find(n) {
if (!this.parents.has(n) || n === this.parents.get(n)) {
return n;
} else {
let p = this.find(this.parents.get(n));
this.parents.set(n, p);
return p;
}
}
union(m, n) {
let x = this.find(m);
let y = this.find(n);
if (x !== y) {
if (x < y) {
this.parents.set(y, x);
} else {
this.parents.set(x, y);
}
}
}
}