2021-08-02:按公因数计算最大组件大小。给定一个由不同正整数的组成的非空数组 A,考虑下面的图:有 A.length 个节点,按从 A[0] 到 A[A.length - 1] 标记;只有当 A[i] 和 A[j] 共用一个大于 1 的公因数时,A[i] 和 A[j] 之间才有一条边。返回图中最大连通组件的大小。

福大大 答案2021-08-02:

算出每个的公因数,然后并查集。
时间复杂度: O(N*sqrt(V))。
空间复杂度: O(N)。

代码用golang编写。代码如下:

package main

import (
    "fmt"
    "math"
)

func main() {
    arr := []int{2, 3, 6, 7, 4, 12, 21, 39}
    ret := largestComponentSize2(arr)
    fmt.Println(ret)
}
func largestComponentSize2(arr []int) int {
    N := len(arr)
    // arr中,N个位置,在并查集初始时,每个位置自己是一个集合
    unionFind := NewUnionFind(N)
    //      key 某个因子   value 哪个位置拥有这个因子
    fatorsMap := make(map[int]int)
    for i := 0; i < N; i++ {
        num := arr[i]
        // 求出根号N, -> limit
        limit := int(math.Sqrt(float64(num)))
        for j := 1; j <= limit; j++ {
            if num%j == 0 {
                if j != 1 {

                    if _, ok := fatorsMap[j]; !ok {
                        fatorsMap[j] = i
                    } else {
                        unionFind.union(fatorsMap[j], i)
                    }
                }
                other := num / j
                if other != 1 {
                    if _, ok := fatorsMap[other]; !ok {
                        fatorsMap[other] = i
                    } else {
                        unionFind.union(fatorsMap[other], i)
                    }
                }
            }
        }
    }
    return unionFind.maxSize()
}

// O(1)
// m,n 要是正数,不能有任何一个等于0
func gcd(a int, b int) int {
    if b == 0 {
        return a
    } else {
        return gcd(b, a%b)
    }
}

type UnionFind struct {
    parents []int
    sizes   []int
    help    []int
}

func NewUnionFind(N int) *UnionFind {
    res := &UnionFind{}
    res.parents = make([]int, N)
    res.sizes = make([]int, N)
    res.help = make([]int, N)
    for i := 0; i < N; i++ {
        res.parents[i] = i
        res.sizes[i] = 1
    }
    return res
}

func (this *UnionFind) maxSize() int {
    ans := 0
    for _, size := range this.sizes {
        ans = getMax(ans, size)
    }
    return ans
}

func getMax(a int, b int) int {
    if a > b {
        return a
    } else {
        return b
    }
}

func (this *UnionFind) find(i int) int {
    hi := 0
    for i != this.parents[i] {
        this.help[hi] = i
        hi++
        i = this.parents[i]
    }
    for hi--; hi >= 0; hi-- {
        this.parents[this.help[hi]] = i
    }
    return i
}

func (this *UnionFind) union(i int, j int) {
    f1 := this.find(i)
    f2 := this.find(j)
    if f1 != f2 {
        big := twoSelectOne(this.sizes[f1] >= this.sizes[f2], f1, f1)
        small := twoSelectOne(big == f1, f2, f1)
        this.parents[small] = big
        this.sizes[big] = this.sizes[f1] + this.sizes[f2]
    }
}

func twoSelectOne(c bool, a int, b int) int {
    if c {
        return a
    } else {
        return b
    }
}

执行结果如下:
图片


左神java代码