Technology

Leetcode Detect Cycle In Undirected Graph

Detecting cycles in an undirected graph is a fundamental problem in graph theory and is frequently encountered in coding interviews, competitive programming, and algorithm courses. On platforms like LeetCode, this problem tests a programmer’s understanding of graph traversal techniques and the ability to implement efficient algorithms to solve real-world challenges. An undirected graph is composed of nodes connected by edges, and a cycle occurs when a path starts and ends at the same node without retracing any edge. Understanding how to detect such cycles is essential for ensuring the correctness of algorithms in network design, dependency resolution, and various other computational problems.

Understanding the Problem

In LeetCode, the problem Detect Cycle in Undirected Graph typically provides a graph in the form of adjacency lists or adjacency matrices. The goal is to determine whether the graph contains any cycle. Since the graph is undirected, each edge is bidirectional, which makes cycle detection slightly different from directed graphs. In an undirected graph, a cycle exists if, during traversal, a node is visited that has already been visited and is not the immediate parent of the current node.

Definitions and Concepts

  • Vertex (Node)A fundamental unit of a graph that can be connected to other vertices by edges.
  • EdgeA connection between two vertices. In undirected graphs, edges do not have a direction.
  • CycleA sequence of edges that starts and ends at the same vertex without repeating edges.
  • Parent NodeIn traversal, the node from which the current node was discovered, used to avoid false positives in cycle detection.

Common Approaches for Cycle Detection

There are multiple algorithms to detect cycles in undirected graphs, and the choice of approach depends on the graph representation and the desired time complexity. The two most popular methods are Depth-First Search (DFS) and Disjoint Set Union (Union-Find).

Depth-First Search (DFS) Method

The DFS approach involves traversing the graph recursively. For each node, the algorithm visits all adjacent nodes. If it encounters a node that has already been visited and is not the parent node of the current vertex, a cycle is detected. This method is simple to implement and effective for graphs of moderate size.

DFS Algorithm Steps

  • Initialize a visited array to keep track of visited vertices.
  • Iterate through each vertex of the graph. If the vertex is not visited, perform DFS.
  • For the current vertex, mark it as visited and explore its neighbors.
  • If a neighbor is visited and is not the parent, return true indicating a cycle.
  • If all vertices are explored without finding a cycle, return false.

DFS Implementation Example

public class DetectCycleUndirected { private int vertices; private List<List<Integer>> adjList; public DetectCycleUndirected(int vertices) { this.vertices = vertices; adjList = new ArrayList<>(); for (int i = 0; i < vertices; i++) { adjList.add(new ArrayList<>()); } } public void addEdge(int u, int v) { adjList.get(u).add(v); adjList.get(v).add(u); } private boolean dfs(int v, boolean[] visited, int parent) { visited[v] = true; for (int neighbor  adjList.get(v)) { if (!visited[neighbor]) { if (dfs(neighbor, visited, v)) { return true; } } else if (neighbor != parent) { return true; // Cycle detected } } return false; } public boolean hasCycle() { boolean[] visited = new boolean[vertices]; for (int i = 0; i < vertices; i++) { if (!visited[i]) { if (dfs(i, visited, -1)) { return true; } } } return false; } }

In this example, the DFS method efficiently detects cycles by recursively exploring each vertex and tracking its parent to avoid false positives.

Union-Find (Disjoint Set) Method

Another effective technique is the Union-Find algorithm, also known as Disjoint Set Union (DSU). This method is particularly efficient for detecting cycles in sparse graphs. The idea is to maintain a set of connected components and merge them as edges are processed. If two vertices of an edge already belong to the same set, adding the edge would form a cycle.

Union-Find Algorithm Steps

  • Initialize a parent array where each vertex is its own parent.
  • For each edge, find the root of each vertex using path compression.
  • If both vertices share the same root, a cycle is detected.
  • If not, perform a union operation to merge the sets.

Union-Find Implementation Example

public class DetectCycleUnionFind { private int[] parent; public DetectCycleUnionFind(int vertices) { parent = new int[vertices]; for (int i = 0; i < vertices; i++) { parent[i] = i; } } private int find(int v) { if (parent[v] != v) { parent[v] = find(parent[v]); // Path compression } return parent[v]; } private void union(int u, int v) { int rootU = find(u); int rootV = find(v); parent[rootU] = rootV; } public boolean hasCycle(int[][] edges) { for (int[] edge  edges) { int u = edge[0], v = edge[1]; int rootU = find(u); int rootV = find(v); if (rootU == rootV) { return true; // Cycle detected } union(u, v); } return false; } }

This method is highly efficient for graphs with many edges because each union and find operation can be performed in nearly constant time using path compression and union by rank optimizations.

Applications of Cycle Detection in Undirected Graphs

Detecting cycles in undirected graphs is not just an academic exercise; it has practical applications in multiple domains. Understanding cycles can help in

  • Network design and loop prevention in communication networks.
  • Detecting deadlocks or circular dependencies in software systems.
  • Analyzing molecular structures in computational chemistry.
  • Verifying constraints in scheduling and task management systems.

Tips for Solving LeetCode Problems Efficiently

When solving the Detect Cycle in Undirected Graph problem on LeetCode, several strategies can improve efficiency and correctness

  • Always check for disconnected components by iterating through all vertices.
  • Use DFS for simplicity and readability, especially for interview scenarios.
  • Use Union-Find for large-scale graphs to optimize performance.
  • Understand the difference between parent nodes and visited nodes to avoid false positives.
  • Test with edge cases such as empty graphs, graphs with a single node, and graphs with multiple components.

Detecting cycles in undirected graphs is a foundational problem in computer science and is frequently tested on coding platforms like LeetCode. By understanding the problem’s underlying concepts, including vertices, edges, cycles, and parent tracking, programmers can approach solutions systematically. Both DFS and Union-Find methods offer effective approaches, with DFS being straightforward and Union-Find offering superior performance for large datasets. Mastering these techniques not only helps solve LeetCode problems but also provides essential skills for real-world applications such as network design, dependency analysis, and scheduling systems. With careful implementation and attention to detail, detecting cycles in undirected graphs becomes a manageable and rewarding problem for any algorithm enthusiast.