Largest Component Size by Common Factor
HardPrompt
You are given an integer array of unique positive integers nums. Consider the following graph:
- There are
nums.lengthnodes, labelednums[0]tonums[nums.length - 1], - There is an undirected edge between
nums[i]andnums[j]ifnums[i]andnums[j]share a common factor greater than1.
Return the size of the largest connected component in the graph.
Example 1:
Input: nums = [4,6,15,35]
Output: 4Example 2:
Input: nums = [20,50,9,63]
Output: 2Example 3:
Input: nums = [2,3,6,7,4,12,21,39]
Output: 8
Constraints:
1 <= nums.length <= 2 * 1041 <= nums[i] <= 105- All the values of
numsare unique.
Approaches
3 approaches with complexity analysis and trade-offs.
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
numsarray. - 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 nodeiand nodejin the adjacency list. - Initialize a
visitedarray to keep track of visited nodes and a variablemaxSizeto store the size of the largest component found so far. - Iterate from
i = 0tonums.length - 1. If nodeihas 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
maxSizewith the maximum of its current value and the size of the new component.
- Start a DFS or BFS traversal from node
- Return
maxSize.
Walkthrough
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
Time
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
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.
Trade-offs
Pros
Simple to understand and directly follows the problem definition.
Cons
Inefficient for the given constraints.
N^2operations 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.
Solutions
Solution
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 walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.