BackeasyGraphsInfosysZomato

Frequency Window Constraint Resolver 3 Solution

Problem Statement

You are tasked with analyzing a network of N nodes representing system components. The network is defined by a list of M connection requests, where each request attempts to link two distinct nodes. Your objective is to determine the final number of isolated clusters (connected components) remaining in the system after processing all valid connections.

Utilize the Union-Find (Disjoint Set Union) data structure to efficiently manage these connections. For each connection request, if the two nodes are already part of the same cluster, the request is ignored. If they belong to different clusters, merge them into a single cluster. The system starts with N isolated nodes, and each successful merge reduces the total count of clusters by one.

Input: An integer N representing the number of nodes, and a 2D array of pairs representing the connection requests. Output: An integer representing the final count of connected components.

Example 1
Input
N = 5, connections = [[0, 1], [2, 3], [4, 4]]
Output
3

Explanation: Initially, there are 5 components: {0}, {1}, {2}, {3}, {4}. Processing [0, 1] merges 0 and 1, resulting in 4 components: {0,1}, {2}, {3}, {4}. Processing [2, 3] merges 2 and 3, resulting in 3 components: {0,1}, {2,3}, {4}. Processing [4, 4] is a self-loop and is ignored. The final count is 3.

Example 2
Input
N = 3, connections = [[0, 1], [1, 2], [0, 2]]
Output
1

Explanation: Start with 3 components: {0}, {1}, {2}. Merge [0, 1] -> {0,1}, {2} (2 components). Merge [1, 2] -> {0,1,2} (1 component). The request [0, 2] finds 0 and 2 are already connected, so it is ignored. The final count is 1.

Example 3
Input
N = 1, connections = []
Output
1

Explanation: There is only one node and no connections. The system remains as a single isolated component. The final count is 1.

Constraints

  • 1 <= N <= 10^5
  • 0 <= connections.length <= 10^5
  • 0 <= connections[i][0], connections[i][1] < N
  • connections[i][0] != connections[i][1] (except for self-loops which are ignored)
Live Compiler1 Free Run Available
Loading Editor...
Test Cases & Output
Click "Run" to test your 1 free compile trial!

🚀 Practice this problem

Run code, get AI hints & track streak

Sign Up Free

Frequency Window Constraint Resolver 3 — Problem Statement & Solution Guide

GraphsEasyUnion-Find Disjoint Set
TimeO(N + M * α(N))
|
SpaceO(N)

Problem Description

You are tasked with analyzing a network of N nodes representing system components. The network is defined by a list of M connection requests, where each request attempts to link two distinct nodes. Your objective is to determine the final number of isolated clusters (connected components) remaining in the system after processing all valid connections.

Utilize the Union-Find (Disjoint Set Union) data structure to efficiently manage these connections. For each connection request, if the two nodes are already part of the same cluster, the request is ignored. If they belong to different clusters, merge them into a single cluster. The system starts with N isolated nodes, and each successful merge reduces the total count of clusters by one.

Input: An integer N representing the number of nodes, and a 2D array of pairs representing the connection requests. Output: An integer representing the final count of connected components.

DSA Pattern Breakdown

DSA Pattern Breakdown

"Frequency Window Constraint Resolver 3"

easy

WHY DOES IT MATTER?

The DSU pattern efficiently solves connectivity queries in dynamic graphs, a frequent requirement in networking, social media analysis, and clustering tasks. It avoids repeated traversals, turning a potentially quadratic problem into linear time, which is critical for scaling to millions of nodes and edges.

OPTIMIZATION CHALLENGE

The breakthrough is recognizing that we don't need the full adjacency structure; we only need a compact parent pointer representation combined with two heuristics—path compression and union by rank—that keep the structure shallow, collapsing the amortized cost of each operation to almost constant time.

REAL-WORLD CONNECTION

Think of a fleet of microservices where each service can form a trust relationship with another. DSU mirrors how a service registry merges trust groups: once two groups establish a link, all members instantly belong to the same trust domain without re‑scanning the entire network.

During an interview, implement DSU with a clear separation: a find function that returns the root with path compression, and a union function that merges by rank/size and decrements a component counter. This modularity reduces bugs and lets you instantly answer follow‑up queries about component count.

COMPLEXITY AT A GLANCE

⏱ Time:O(N + M * α(N))
💾 Space:O(N)

Core Theory — Why This Approach?

The Union‑Find (Disjoint Set Union, DSU) data structure maintains a collection of disjoint sets and supports two operations efficiently: find, which returns the representative (root) of the set containing a given element, and union, which merges two sets. By representing each node as a singleton set initially and processing each connection request with a union, we gradually coalesce nodes that become reachable from one another. The number of connected components after all unions equals the count of distinct roots remaining. Naïve graph traversal (e.g., BFS/DFS after each edge) would require O(N+M) per edge in the worst case, leading to O(N·M) time for large inputs, which quickly exceeds limits. DSU with path compression (flattening the tree during find) and union by rank/size guarantees near‑constant amortized time per operation, yielding an overall O(N + M α(N)) complexity, where α is the inverse Ackermann function, effectively constant for any realistic N.

The optimal paradigm therefore hinges on two key ideas: (1) representing connectivity implicitly via parent pointers rather than explicit adjacency lists, and (2) aggressively flattening the structure during finds so that subsequent operations traverse almost no nodes. This transforms a potentially quadratic process into a linear‑ithmic one, making it suitable for the typical constraints of competitive programming and interview problems where N and M can each reach 10⁵ or higher.

Interview Questions on This Problem

Q1How would you modify the DSU to also keep track of the size of each connected component, and why might that be useful?

Maintain an auxiliary size array where size[root] stores the number of nodes in that component. During a union, attach the smaller tree under the larger and update the size of the new root. This enables O(1) queries for component size, useful for problems that ask for the largest component, threshold checks, or weighted merges.

Q2Explain why path compression alone (without union by rank) still yields near‑linear performance, and give a scenario where adding union by rank provides a measurable benefit.

Path compression flattens the tree each time find is called, ensuring that future finds are O(1) on average, leading to O(M α(N)) time. However, without union by rank, a series of unions could create tall trees before compression occurs, causing occasional deep traversals. Adding union by rank guarantees that the tree height stays logarithmic, reducing the worst‑case depth before compression and improving constant factors, especially when many unions are performed before any finds.

Q3In a distributed system, how could you emulate DSU behavior to track cluster membership across multiple machines?

You can assign each node a leader identifier and use a gossip or consensus protocol to propagate merges: when two clusters need to be united, the leaders exchange messages and agree on a new leader (e.g., the one with higher rank). Each machine updates its local mapping, and path compression is mimicked by periodically re‑routing nodes to the current leader, ensuring eventual consistency of component membership.

Examples

Example 1

Input

N = 5, connections = [[0, 1], [2, 3], [4, 4]]

Output

3

Explanation: Initially, there are 5 components: {0}, {1}, {2}, {3}, {4}. Processing [0, 1] merges 0 and 1, resulting in 4 components: {0,1}, {2}, {3}, {4}. Processing [2, 3] merges 2 and 3, resulting in 3 components: {0,1}, {2,3}, {4}. Processing [4, 4] is a self-loop and is ignored. The final count is 3.

Example 2

Input

N = 3, connections = [[0, 1], [1, 2], [0, 2]]

Output

1

Explanation: Start with 3 components: {0}, {1}, {2}. Merge [0, 1] -> {0,1}, {2} (2 components). Merge [1, 2] -> {0,1,2} (1 component). The request [0, 2] finds 0 and 2 are already connected, so it is ignored. The final count is 1.

Example 3

Input

N = 1, connections = []

Output

1

Explanation: There is only one node and no connections. The system remains as a single isolated component. The final count is 1.

Constraints

  • 1 <= N <= 10^5
  • 0 <= connections.length <= 10^5
  • 0 <= connections[i][0], connections[i][1] < N
  • connections[i][0] != connections[i][1] (except for self-loops which are ignored)

Optimal Approach & Strategy

Initialize a DSU with each node as its own parent, then iterate over each edge and union the two endpoints, decrementing a component counter when a merge occurs.

Brute Force Approach

Build the full adjacency list and run a DFS/BFS from every unvisited node, marking all reachable nodes as visited; repeat until all nodes are processed.

Verified Code Solutions

JavaScript Solution
Time: O(N + M * α(N))
function solution(nums) {
   const unionFind = {};
   let sum = 0;
   for (let i = 0; i < nums.length; i++) {
       sum += nums[i];
       if (!(nums[i] in unionFind)) {
           unionFind[nums[i]] = nums[i];
       }
   }
   return sum;
}

Asked in Top Tech Interviews

InfosysZomato

Solve in Interative Editor

Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.