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

269 阅读1分钟

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

952. 按公因数计算最大组件大小 - 力扣(LeetCode)

给定一个由不同正整数的组成的非空数组 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^4
  • 1 <= nums[i] <= 10^5
  • nums 中所有值都 不同

解题

/**
 * @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);
      }
    }
  }
}