We use cookies (including Google cookies) to personalize ads and analyze traffic. By continuing to use our site, you accept our Privacy Policy.

Divide Nodes Into the Maximum Number of Groups

Number: 2583

Difficulty: Hard

Paid? No

Companies: Microsoft, Amazon, Uber, Google


Problem Description

Given an undirected graph with n nodes (labeled from 1 to n) and an array of edges, divide all nodes into m groups (with groups numbered consecutively starting at 1) so that every edge connects two nodes whose group numbers differ by exactly one. Return the maximum possible m under these conditions, or -1 if no valid grouping exists.


Key Insights

  • Every edge’s constraint (|group[u]-group[v]| = 1) forces a “layered” assignment on each connected component.
  • In any valid assignment, if we treat a group as a “level” (or distance) from a chosen start node, adjacent nodes must lie on consecutive levels.
  • A necessary condition is that each connected component must be bipartite. However, to maximize m, each component should be “stretched” as far as possible.
  • For a connected component, the maximum number of distinct groups we can assign equals (diameter + 1), where the diameter is the maximum distance (in the valid layering) between any two nodes.
  • For disconnected components, because there are no inter-component edge constraints, we can “chain” the layers across components. By overlapping group boundaries between components, the overall maximum number of groups equals 1 plus the sum of the diameters of each component.

Space and Time Complexity

Time Complexity: O(N*(N + E)) in the worst case because for each component we perform a BFS starting from every node. Space Complexity: O(N + E) for the graph, visited markers, and BFS queues.


Solution

The approach is as follows:

  1. Build the graph as an adjacency list.
  2. Use a DFS (or BFS) to find all nodes in each connected component.
  3. For each component, try using every node as a starting point to “layer” the nodes via BFS. In each BFS, assign a distance (or group number offset) starting from 0 and, importantly, check that for every edge, the difference between the levels is exactly 1. If any inconsistency is found, the graph does not admit any valid grouping (return -1).
  4. The maximum number of groups achievable within a component is the maximum distance found (over all BFS runs) plus 1.
  5. Since different components are not connected, their assignments can be “chained” together. In an optimal arrangement, the overall number of groups equals 1 plus the sum of each component’s diameter.
  6. Return this overall maximum group count.

Code Solutions

# Python solution for dividing nodes into maximum groups

from collections import deque, defaultdict

def maxGroups(n, edges):
    # Build graph as an adjacency list
    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)
    
    visited = [False] * (n + 1)  # To keep track of visited nodes overall
    component_diameters = []  # Store maximum BFS distances (diameters) per component
    
    # Helper routine to get all nodes in the current component using DFS
    def get_component(node):
        comp = []
        stack = [node]
        visited[node] = True
        while stack:
            cur = stack.pop()
            comp.append(cur)
            for neigh in graph[cur]:
                if not visited[neigh]:
                    visited[neigh] = True
                    stack.append(neigh)
        return comp
    
    # Process each node/component
    for node in range(1, n + 1):
        if not visited[node]:
            comp = get_component(node)
            # For an isolated node, the diameter is 0.
            if len(comp) == 1:
                component_diameters.append(0)
                continue
            comp_diameter = 0
            # Try every node in the component as the BFS starting point.
            for start in comp:
                dist = {start: 0}  # Distance assignment for BFS (layering)
                q = deque([start])
                valid = True
                while q and valid:
                    u = q.popleft()
                    for v in graph[u]:
                        if v not in dist:
                            # Assign neighbor to next level (group)
                            dist[v] = dist[u] + 1
                            q.append(v)
                        else:
                            # Check that every edge has difference exactly one
                            if abs(dist[v] - dist[u]) != 1:
                                valid = False
                                break
                if not valid:
                    return -1  # Inconsistency detected
                # Update the component diameter with maximum distance found in this BFS
                comp_diameter = max(comp_diameter, max(dist.values()))
            component_diameters.append(comp_diameter)
    
    # For disconnected components, we can "chain" their layers.
    # Overall groups = 1 + sum(each component's diameter)
    overall_groups = 1 + sum(component_diameters)
    return overall_groups

# Example usage:
# print(maxGroups(6, [[1,2],[1,4],[1,5],[2,6],[2,3],[4,6]]))  # Expected output: 4
# print(maxGroups(3, [[1,2],[2,3],[3,1]]))  # Expected output: -1
← Back to All Questions