0
0
DSA Typescriptprogramming

Bipartite Graph Check in DSA Typescript

Choose your learning style9 modes available
Mental Model
A bipartite graph can be split into two groups where no nodes inside the same group connect to each other.
Analogy: Imagine two teams playing a game where players only pass the ball to the other team, never to their own team members.
Group A: 1 -> 3 -> 5
Group B: 2 -> 4 -> 6
Edges only go between groups, never inside one group.
Dry Run Walkthrough
Input: Graph with edges: 1-2, 2-3, 3-4, 4-1
Goal: Check if this graph can be divided into two groups with no edges inside the same group
Step 1: Start coloring node 1 with color 0
Node colors: [1:0, 2:null, 3:null, 4:null]
Why: We pick a color for the first node to start the grouping
Step 2: Color neighbors of 1 (nodes 2 and 4) with color 1
Node colors: [1:0, 2:1, 3:null, 4:1]
Why: Neighbors must have opposite color to avoid same-group edges
Step 3: Color neighbor of 2 (node 3) with color 0
Node colors: [1:0, 2:1, 3:0, 4:1]
Why: Neighbors of node 2 get opposite color to 2
Step 4: Check neighbors of 3 (nodes 2 and 4) for color conflicts
Node colors: [1:0, 2:1, 3:0, 4:1]
Why: Neighbors have opposite colors, no conflict found
Step 5: Check neighbors of 4 (nodes 1 and 3) for color conflicts
Node colors: [1:0, 2:1, 3:0, 4:1]
Why: Neighbors have opposite colors, no conflict found
Result:
Node colors: [1:0, 2:1, 3:0, 4:1] -> Graph is bipartite
Annotated Code
DSA Typescript
class Graph {
  adjacencyList: Map<number, number[]>;

  constructor(edges: [number, number][]) {
    this.adjacencyList = new Map();
    for (const [u, v] of edges) {
      if (!this.adjacencyList.has(u)) this.adjacencyList.set(u, []);
      if (!this.adjacencyList.has(v)) this.adjacencyList.set(v, []);
      this.adjacencyList.get(u)!.push(v);
      this.adjacencyList.get(v)!.push(u);
    }
  }

  isBipartite(): boolean {
    const color = new Map<number, number>();

    for (const node of this.adjacencyList.keys()) {
      if (!color.has(node)) {
        if (!this.dfsCheck(node, color, 0)) return false;
      }
    }
    return true;
  }

  private dfsCheck(node: number, color: Map<number, number>, c: number): boolean {
    color.set(node, c); // assign color to current node

    for (const neighbor of this.adjacencyList.get(node)!) {
      if (!color.has(neighbor)) {
        if (!this.dfsCheck(neighbor, color, 1 - c)) return false; // assign opposite color
      } else if (color.get(neighbor) === c) {
        return false; // neighbor has same color, not bipartite
      }
    }
    return true;
  }
}

// Driver code
const edges: [number, number][] = [[1, 2], [2, 3], [3, 4], [4, 1]];
const graph = new Graph(edges);
console.log(graph.isBipartite() ? "Graph is bipartite" : "Graph is not bipartite");
color.set(node, c); // assign color to current node
assign color to current node to mark its group
for (const neighbor of this.adjacencyList.get(node)!) {
check all neighbors of current node
if (!color.has(neighbor)) {
if neighbor not colored, assign opposite color recursively
if (!this.dfsCheck(neighbor, color, 1 - c)) return false; // assign opposite color
recursive call to color neighbor with opposite color
else if (color.get(neighbor) === c) {
if neighbor has same color, graph is not bipartite
OutputSuccess
Graph is bipartite
Complexity Analysis
Time: O(V + E) because we visit every node and edge once during DFS
Space: O(V) for storing colors and recursion stack in worst case
vs Alternative: Compared to BFS approach, DFS uses recursion but both have same time and space complexity
Edge Cases
Empty graph
Returns true since no edges mean no conflicts
DSA Typescript
for (const node of this.adjacencyList.keys()) { if (!color.has(node)) { ... } }
Graph with one node and no edges
Returns true as single node can be colored any color
DSA Typescript
color.set(node, c); // assign color to current node
Graph with odd cycle (e.g., triangle 1-2-3-1)
Returns false because odd cycle cannot be bipartite
DSA Typescript
else if (color.get(neighbor) === c) { return false; }
When to Use This Pattern
When a problem asks if nodes can be split into two groups with no internal edges, use bipartite check with graph coloring to detect conflicts.
Common Mistakes
Mistake: Not checking all connected components, missing disconnected nodes
Fix: Loop over all nodes and run DFS/BFS if not colored yet
Mistake: Assigning same color to neighbors instead of opposite
Fix: Assign opposite color using 1 - current color
Summary
Checks if a graph's nodes can be divided into two groups with no edges inside the same group.
Use when you need to separate nodes into two sets without internal connections.
The key is to color nodes alternately and detect any color conflicts.