algoadvance

Given a set of n people (numbered from 1 to n), we would like to split everyone into two groups of any size. Each person may dislike some other people, and they should not go into the same group.

We are given a 2D array dislikes where each dislikes[i] = [a_i, b_i] indicates that person a_i dislikes person b_i. Return true if and only if it is possible to split everyone into two groups in this way.

Clarifying Questions

  1. What is the range of n?
    • Typically, constraints will be given in the problem statement. Let’s assume a reasonable range like 1 ≤ n ≤ 2000.
  2. Can there be duplicate dislike pairs in dislikes array?
    • Typically, no duplicate pairs are expected, but this can be clarified or handled in code.
  3. Is it guaranteed that the dislikes array will not contain self-loops? (i.e., person dislikes themselves)
    • Usually, this can be assumed but can be gone through preprocessing to ensure the data integrity.

Strategy

To solve this problem, we can model it as a graph problem:

General Steps:

  1. Graph Representation: Use an adjacency list to store the graph.
  2. Bipartiteness Check: Use Depth-First Search (DFS) or Breadth-First Search (BFS) to try to color the graph.
    • If at any point, we find a conflict (i.e., two adjacent nodes have the same color), the graph is not bipartite, and we return false.
    • Otherwise, after all nodes are processed, we return true.

Code

from collections import defaultdict, deque

def possibleBipartition(n, dislikes):
    # Step 1: Create an adjacency list for the graph
    graph = defaultdict(list)
    for u, v in dislikes:
        graph[u].append(v)
        graph[v].append(u)

    # Step 2: Initialize a color array for nodes (0: uncolored, 1: color1, -1: color2)
    color = [0] * (n + 1)
    
    # Step 3: BFS/DFS to check for bipartiteness
    def bfs(start):
        queue = deque([start])
        color[start] = 1  # Start coloring with color 1
        
        while queue:
            node = queue.popleft()
            for neighbor in graph[node]:
                if color[neighbor] == 0:  # If the neighbor hasn't been colored yet
                    color[neighbor] = -color[node]  # Color with the opposite color
                    queue.append(neighbor)
                elif color[neighbor] == color[node]:  # If the neighbor has the same color
                    return False
        return True

    # Step 4: Check each component of the graph
    for person in range(1, n + 1):
        if color[person] == 0:  # Not yet colored, thus needs to be checked
            if not bfs(person):
                return False
                
    return True

Time Complexity

Thus, the overall time complexity is O(V + E), which is efficient for the given constraints.

Try our interview co-pilot at AlgoAdvance.com