[LC952]按公因数计算最大组件大小

题目描述

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

有 nums.length 个节点,按从 nums[0] 到 nums[nums.length - 1] 标记;
只有当 nums[i] 和 nums[j] 共用一个大于 1 的公因数时,nums[i] 和 nums[j]之间才有一条边。
返回 图中最大连通组件的大小 。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/largest-component-size-by-common-factor

提示:
1 <= nums.length <= 2 * 10^4
1 <= nums[i] <= 10^5
nums 中所有值都 不同

题目分析

最直接的想法是去遍历数组中的每一个数num。对于每一个数,可以考查其所有因子,并使用并查集将因子与这个数本身归为一个集合中,在这个过程中,数组中具有大于1的num之间也会被合并入相同的集合。最后,我们可以重新遍历nums数组,并通过并查集查询每个num对应的root,并统计对应的频次,保留最大的频次,就可以得到最大联通组件的大小。

代码

golang
type Union struct {
	parent, rank []int
	//rank按秩合并
}

func newUnion(n int) Union {
	parent := make([]int, n)
	for i := range parent {
		parent[i] = i
	}
	return Union{parent, make([]int, n)}
}

func (u Union) find(x int) int {
	if u.parent[x] != x {
	//路径压缩
		u.parent[x] = u.find(u.parent[x])
	}
	return u.parent[x]
}

func (u Union) merge(x int, y int) {
	rootX := u.find(x)
	rootY := u.find(y)
	if rootX != rootY {
		if u.rank[rootY] > u.rank[rootX] {
			u.parent[rootX] = rootY
		} else if u.rank[rootY] > u.rank[rootX] {
			u.parent[rootY] = rootX
		} else {
			u.parent[rootX] = rootY
			//更新秩
			u.rank[rootY]++
		}
	}
}
func max(x int, y int) int{
	if x > y {
		return x
	}
	return y
}

func largestComponentSize(nums []int) int {
	maxVal := 0
	for _, num := range nums{
		maxVal = max(num, maxVal)
	}
	union := newUnion(maxVal +1)
	for _, num := range nums{
	//暴力筛
		for i := 2; i * i <= num; i++{
			if num % i == 0{
				union.merge(num, i)
				union.merge(num, num/i)
			}
		}
	}
	rtn := 0
	arr := make([]int, maxVal+1)
	for _, num := range nums{
		root := union.find(num)
		arr[root] ++
		rtn = max(rtn, arr[root])
	}
	return rtn
}
posted @ 2022-07-31 00:01  XinStar  阅读(74)  评论(0编辑  收藏  举报