Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources
Detect Cycle in Undirected Graph

Detect Cycle in Undirected Graph

Problem Statement

You’re a graph investigator checking an undirected graph for cycles. Given vertices and edges, return true if a cycle exists, false otherwise. This medium-level DFS challenge is a loop hunt—track parents to spot back edges!

Example

Input: V = 4, edges = [[0,1],[1,2],[2,3],[3,1]]

Graph:

0---1
    |   |
    |   |
    3---2

Output: true (1-2-3-1 cycle)

Input: V = 3, edges = [[0,1],[1,2]]

Output: false (Tree, no cycle)

Code

Java
Python
JavaScript
class Solution {
    public boolean hasCycle(int V, int[][] edges) {
        List> graph = new ArrayList<>();
        for (int i = 0; i < V; i++) graph.add(new ArrayList<>());
        for (int[] edge : edges) {
            graph.get(edge[0]).add(edge[1]);
            graph.get(edge[1]).add(edge[0]);
        }
        boolean[] visited = new boolean[V];
        for (int i = 0; i < V; i++) {
            if (!visited[i] && dfs(graph, i, -1, visited)) return true;
        }
        return false;
    }
    private boolean dfs(List> graph, int node, int parent, boolean[] visited) {
        visited[node] = true;
        for (int neighbor : graph.get(node)) {
            if (!visited[neighbor]) {
                if (dfs(graph, neighbor, node, visited)) return true;
            } else if (neighbor != parent) {
                return true; // Back edge
            }
        }
        return false;
    }
}
            
from collections import defaultdict
def has_cycle(V, edges):
    graph = defaultdict(list)
    for u, v in edges:
        graph[u].append(v)
        graph[v].append(u)
    visited = [False] * V
    def dfs(node, parent):
        visited[node] = True
        for neighbor in graph[node]:
            if not visited[neighbor]:
                if dfs(neighbor, node):
                    return True
            elif neighbor != parent:
                return True
        return False
    for i in range(V):
        if not visited[i] and dfs(i, -1):
            return True
    return False
            
function hasCycle(V, edges) {
    let graph = Array(V).fill().map(() => []);
    for (let [u, v] of edges) {
        graph[u].push(v);
        graph[v].push(u);
    }
    let visited = new Array(V).fill(false);
    function dfs(node, parent) {
        visited[node] = true;
        for (let neighbor of graph[node]) {
            if (!visited[neighbor]) {
                if (dfs(neighbor, node)) return true;
            } else if (neighbor !== parent) {
                return true;
            }
        }
        return false;
    }
    for (let i = 0; i < V; i++) {
        if (!visited[i] && dfs(i, -1)) return true;
    }
    return false;
}
            

Explanation

  • DFS Insight: Cycle exists if a visited node isn’t the parent—indicates a back edge.
  • Flow: Build graph, DFS with parent tracking, check for non-parent visited nodes.
  • Example Walkthrough: [0,1],[1,2],[2,0] → 0→1→2→0 (not parent) → true.
  • Union-Find Alt: Merge edges, detect if already connected—O(V) space.
  • Disconnected Graphs: Check all components to ensure full coverage.

Note

Time complexity: O(V + E), Space complexity: O(V + E). A cycle-spotting spectacle—DFS brilliance!