LeetCode //C - 952. Largest Component Size by Common Factor

952. Largest Component Size by Common Factor

You are given an integer array of unique positive integers nums. Consider the following graph:

  • There are nums.length nodes, labeled nums[0] to nums[nums.length - 1],
  • There is an undirected edge between nums[i] and nums[j] if nums[i] and nums[j] share a common factor greater than 1.

Return the size of the largest connected component in the graph.
 

Example 1:

在这里插入图片描述

Input: nums = [4,6,15,35]
Output: 4

Example 2:

在这里插入图片描述

Input: nums = [20,50,9,63]
Output: 2

Example 3:

在这里插入图片描述

Input: nums = [2,3,6,7,4,12,21,39]
Output: 8

Constraints:
  • 1 < = n u m s . l e n g t h < = 2 ∗ 1 0 4 1 <= nums.length <= 2 * 10^4 1<=nums.length<=2104
  • 1 < = n u m s [ i ] < = 1 0 5 1 <= nums[i] <= 10^5 1<=nums[i]<=105
  • All the values of nums are unique.

From: LeetCode
Link: 952. Largest Component Size by Common Factor


Solution:

Ideas:
  • Goal: Connect numbers that share a common factor > 1 and find the largest connected component.

  • Use Union–Find (DSU):

    • Each number starts in its own set.
    • When two numbers share a factor, we union their sets.
  • Prime Factorization for Efficiency:

    • Precompute the smallest prime factor (SPF) for every number up to max(nums).
    • Quickly factor each number using SPF.
  • Mapping factor → index:

    • For each prime factor, store the first index of a number that contains it.
    • When another number shares that same factor → union them.
  • Finally:

    • Count the size of each connected component in DSU.
    • Return the largest component size.
Code:
typedef struct {
    int *parent;
    int *compSize;
    int n;
} DSU;

static int dsu_find(DSU *dsu, int x) {
    if (dsu->parent[x] != x)
        dsu->parent[x] = dsu_find(dsu, dsu->parent[x]);
    return dsu->parent[x];
}

static void dsu_union(DSU *dsu, int x, int y) {
    int rx = dsu_find(dsu, x);
    int ry = dsu_find(dsu, y);
    if (rx == ry) return;

    // union by size
    if (dsu->compSize[rx] < dsu->compSize[ry]) {
        int tmp = rx; rx = ry; ry = tmp;
    }
    dsu->parent[ry] = rx;
    dsu->compSize[rx] += dsu->compSize[ry];
}

int largestComponentSize(int* nums, int numsSize) {
    if (numsSize == 0) return 0;

    int maxVal = 0;
    for (int i = 0; i < numsSize; ++i)
        if (nums[i] > maxVal) maxVal = nums[i];

    // Build DSU on indices 0..numsSize-1
    DSU dsu;
    dsu.n = numsSize;
    dsu.parent = (int*)malloc(numsSize * sizeof(int));
    dsu.compSize = (int*)malloc(numsSize * sizeof(int));
    for (int i = 0; i < numsSize; ++i) {
        dsu.parent[i] = i;
        dsu.compSize[i] = 1;
    }

    // Smallest prime factor sieve up to maxVal
    int *spf = (int*)malloc((maxVal + 1) * sizeof(int));
    memset(spf, 0, (maxVal + 1) * sizeof(int));
    for (int i = 2; i * i <= maxVal; ++i) {
        if (!spf[i]) {
            spf[i] = i;
            for (int j = i * i; j <= maxVal; j += i)
                if (!spf[j]) spf[j] = i;
        }
    }
    for (int i = 2; i <= maxVal; ++i)
        if (!spf[i]) spf[i] = i;  // fill remaining primes

    // For each prime factor, remember first index of a number having it
    int *firstIdx = (int*)malloc((maxVal + 1) * sizeof(int));
    for (int i = 0; i <= maxVal; ++i) firstIdx[i] = -1;

    // Connect numbers sharing a common prime factor
    for (int i = 0; i < numsSize; ++i) {
        int x = nums[i];
        if (x <= 1) continue;   // 1 has no prime factors >1

        while (x > 1) {
            int p = spf[x];
            // skip repeated powers of the same prime
            while (x % p == 0) x /= p;

            if (firstIdx[p] == -1) {
                firstIdx[p] = i;
            } else {
                dsu_union(&dsu, i, firstIdx[p]);
            }
        }
    }

    // Find largest component size
    int ans = 0;
    for (int i = 0; i < numsSize; ++i) {
        if (dsu.parent[i] == i && dsu.compSize[i] > ans)
            ans = dsu.compSize[i];
    }

    free(dsu.parent);
    free(dsu.compSize);
    free(spf);
    free(firstIdx);

    return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Navigator_Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值