Largest Component Size by Common Factor

HARD

Description

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 <= nums.length <= 2 * 104
  • 1 <= nums[i] <= 105
  • All the values of nums are unique.

Approaches

Checkout 3 different approaches to solve Largest Component Size by Common Factor. Click on different approaches to view the approach and algorithm in detail.

Brute-Force Graph Construction and Traversal

This approach directly translates the problem statement into a graph data structure. It builds an explicit graph where nodes are the numbers from the input array. An edge is added between two nodes if their corresponding numbers share a common factor greater than 1. After building the graph, a standard graph traversal algorithm like Depth-First Search (DFS) or Breadth-First Search (BFS) is used to find the sizes of all connected components.

Algorithm

  • Initialize an adjacency list to represent the graph. The nodes correspond to the indices of the nums array.
  • Iterate through every unique pair of numbers (nums[i], nums[j]) from the input array.
  • For each pair, calculate their Greatest Common Divisor (GCD) using the Euclidean algorithm.
  • If gcd(nums[i], nums[j]) > 1, add an edge between node i and node j in the adjacency list.
  • Initialize a visited array to keep track of visited nodes and a variable maxSize to store the size of the largest component found so far.
  • Iterate from i = 0 to nums.length - 1. If node i has not been visited:
    • Start a DFS or BFS traversal from node i.
    • Count the number of nodes in the component discovered by the traversal.
    • Update maxSize with the maximum of its current value and the size of the new component.
  • Return maxSize.
class Solution {
    public int largestComponentSize(int[] nums) {
        int n = nums.length;
        List<List<Integer>> adj = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            adj.add(new ArrayList<>());
        }

        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (gcd(nums[i], nums[j]) > 1) {
                    adj.get(i).add(j);
                    adj.get(j).add(i);
                }
            }
        }

        boolean[] visited = new boolean[n];
        int maxSize = 0;
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                int currentSize = dfs(i, adj, visited);
                maxSize = Math.max(maxSize, currentSize);
            }
        }
        return maxSize;
    }

    private int dfs(int u, List<List<Integer>> adj, boolean[] visited) {
        visited[u] = true;
        int count = 1;
        for (int v : adj.get(u)) {
            if (!visited[v]) {
                count += dfs(v, adj, visited);
            }
        }
        return count;
    }

    private int gcd(int a, int b) {
        while (b != 0) {
            int temp = b;
            b = a % b;
            a = temp;
        }
        return a;
    }
}

Complexity Analysis

Time Complexity: O(N^2 * log(M)), where N is the length of `nums` and M is the maximum value in `nums`. Building the graph requires checking `O(N^2)` pairs, and each check involves a GCD calculation which takes `O(log(M))` time. The subsequent graph traversal is dominated by the graph construction time.Space Complexity: O(N^2), where N is the number of elements in `nums`. This is for storing the adjacency list, which can have up to `O(N^2)` edges in a dense graph.

Pros and Cons

Pros:
  • Simple to understand and directly follows the problem definition.
Cons:
  • Inefficient for the given constraints. N^2 operations are too slow.
  • The space complexity can be very high, up to O(N^2), if the graph is dense.
  • This approach will likely result in a "Time Limit Exceeded" or "Memory Limit Exceeded" error on competitive programming platforms.

Code Solutions

Checking out 3 solutions in different languages for Largest Component Size by Common Factor. Click on different languages to view the code.

class UnionFind { int [] p ; UnionFind ( int n ) { p = new int [ n ]; for ( int i = 0 ; i < n ; ++ i ) { p [ i ] = i ; } } void union ( int a , int b ) { int pa = find ( a ), pb = find ( b ); if ( pa != pb ) { p [ pa ] = pb ; } } int find ( int x ) { if ( p [ x ] != x ) { p [ x ] = find ( p [ x ]); } return p [ x ]; } } class Solution { public int largestComponentSize ( int [] nums ) { int m = 0 ; for ( int v : nums ) { m = Math . max ( m , v ); } UnionFind uf = new UnionFind ( m + 1 ); for ( int v : nums ) { int i = 2 ; while ( i <= v / i ) { if ( v % i == 0 ) { uf . union ( v , i ); uf . union ( v , v / i ); } ++ i ; } } int [] cnt = new int [ m + 1 ]; int ans = 0 ; for ( int v : nums ) { int t = uf . find ( v ); ++ cnt [ t ]; ans = Math . max ( ans , cnt [ t ]); } return ans ; } }

Video Solution

Watch the video walkthrough for Largest Component Size by Common Factor



Algorithms:

Union Find

Patterns:

MathNumber Theory

Data Structures:

ArrayHash Table

Subscribe to Scale Engineer newsletter

Learn about System Design, Software Engineering, and interview experiences every week.

No spam, unsubscribe at any time.