目录

LC 952. 按公因数计算最大组件大小 (opens new window) (opens new window)

困难

# 问题描述

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

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

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

示例 1:

示例1

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

示例 2:

示例2

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

示例 3:

示例3

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

提示:

  • 1 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 105
  • nums 中所有值都 不同

# 并查集

numsnums 中最大值为 maxmax,对应每个不大于 maxmax 的数 numnum, 对于范围 [2,num][2, \sqrt{num}] 内的每个正整数 ii,如果 iinumnum 的因数,则 numnumiinumi\dfrac{num}{i} 都属于同一个组件。使用并查集实现组件的计算,最终遍历 numsnums 找出最大的连通组件

/**
 * @param {number[]} nums
 * @return {number}
 */
var largestComponentSize = function (nums) {
  const max = Math.max(...nums)
  const parent = new Array(max + 1).fill(0).map((_, i) => i)
  const find = (x) => {
    if (parent[x] !== x) {
      parent[x] = find(parent[x])
    }
    return parent[x]
  }
  const union = (x, y) => {
    let parentX = find(x)
    let parentY = find(y)
    if (parentX !== parentY) {
      parent[parentX] = parentY
    }
  }
  for (const num of nums) {
    for (let i = 2; i * i <= num; i++) {
      if (num % i === 0) {
        union(num, i)
        union(num, num / i)
      }
    }
  }
  const cnts = new Array(max + 1).fill(0)
  let ans = 0
  for (const num of nums) {
    ans = Math.max(ans, ++cnts[find(num)])
  }
  return ans
}
  • 时间复杂度:O(nm)O(n\sqrt{m}),其中 nnnumsnums 的长度,mm numsnums 中最大值。
  • 空间复杂度:O(m)O(m)mmnumsnums 中最大值。
上次更新: 2023/01/31 19:48:05

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 , 转载请注明出处!