Skip to main content

Depth First Search

Depth First Search on Disconnected Components

Problem Statement

You are given a set of edgesn, where edges represents the connection between two nodes, n represents the number of nodes, and src represents the source node. Traverse each component in the graph in a depth-first fashion.

Example 1

Input:
edges = [[0, 1], [0, 2], [1, 2], [1, 3], [1, 4], [2, 5], [3, 4], [3, 5], [6, 7], [7, 8]]
n = 9
Output: 
0 1 2 5 3 4 6 7 8

Video Solution

Java Code

import java.util.ArrayList;
import java.util.List;

class DFSDisconnectedGraph {

    public List<List<Integer>> buildGraph(int[][] edges, int n) {
        List<List<Integer>> graph = new ArrayList<>();
        
        for(int i = 0; i < n; i++) {
            graph.add(new ArrayList<>());
        }

        for(int[] edge : edges) {
            graph.get(edge[0]).add(edge[1]);
            graph.get(edge[1]).add(edge[0]);
        }

        return graph;

    }

    private void solve(int node, List<Integer> dfsAnswer, List<List<Integer>> graph, boolean[] visited) {
        dfsAnswer.add(node);
        visited[node] = true;
        for(int nbr : graph.get(node)) {
            if(!visited[nbr]) {
                solve(nbr, dfsAnswer, graph, visited);
            }
        }
    }

    private List<Integer> depthFirstSearch(int[][] edges, int n) {
        List<List<Integer>> graph = buildGraph(edges, n);
        List<Integer> dfsAnswer = new ArrayList<>();
        boolean[] visited = new boolean[n];
        for(int src = 0; src < n; src++) {
            if(!visited[src]) {
                solve(src, dfsAnswer, graph, visited);
            }
        }
        return dfsAnswer;
        
    }

    public static void main(String[] args) {
        int[][] edges = new int[][]{{0, 1}, {0, 2}, {1, 2}, {1, 3}, {1, 4}, {2, 5}, {3, 4}, {3, 5}, {6, 7}, {7, 8}};
        int n = 9;
        
        DFSDisconnectedGraph dfs = new DFSDisconnectedGraph();
        
        List<Integer> dfsAnswer = dfs.depthFirstSearch(edges, n);
        for(int node : dfsAnswer) {
            System.out.print(node + " ");
        }
    }
}

C++ Code

#include<bits/stdc++.h>
using namespace std;

class DFSDisconnectedGraph {
public:
    vector<vector<int>> buildGraph(vector<vector<int>>& edges, int n) {
        vector<vector<int>> graph(n);
        
        for (const auto& edge : edges) {
            graph[edge[0]].push_back(edge[1]);
            graph[edge[1]].push_back(edge[0]);
        }

        return graph;
    }

    void solve(int node, vector<int>& dfsAnswer, vector<vector<int>>& graph, vector<bool>& visited) {
        dfsAnswer.push_back(node);
        visited[node] = true;
        for (int nbr : graph[node]) {
            if (!visited[nbr]) {
                solve(nbr, dfsAnswer, graph, visited);
            }
        }
    }

    vector<int> depthFirstSearch(vector<vector<int>>& edges, int n) {
        vector<vector<int>> graph = buildGraph(edges, n);
        vector<int> dfsAnswer;
        vector<bool> visited(n, false);
        for(int src = 0; src < n; src++) {
            if(!visited[src]) {
                solve(src, dfsAnswer, graph, visited);
            }
        }
        return dfsAnswer;
    }
};

int main() {
    vector<vector<int>> edges = {{0, 1}, {0, 2}, {1, 2}, {1, 3}, {1, 4}, {2, 5}, {3, 4}, {3, 5}, {6, 7}, {7, 8}};
    int n = 9;
    
    DFSDisconnectedGraph dfs;
    
    vector<int> dfsAnswer = dfs.depthFirstSearch(edges, n);
    for (int node : dfsAnswer) {
        cout << node << " ";
    }

    return 0;
}

Python Code

from typing import List

class DFSDisconnectedGraph:

    def __init__(self):
        pass

    def build_graph(self, edges, n):
        graph = []

        for i in range(n):
            graph.append(list())

        for edge in edges:
            graph[edge[0]].append(edge[1])
            graph[edge[1]].append(edge[0])

        return graph

    def solve(self, node, dfs_answer, graph, visited):
        dfs_answer.append(node)
        visited[node] = True
        for nbr in graph[node]:
            if not visited[nbr]:
                self.solve(nbr, dfs_answer, graph, visited)

    def depthFirstSearch(self, edges, n):
        graph = self.build_graph(edges, n)
        dfs_answer = []
        visited = [False] * n
        for src in range(n):
            if visited[src] is not True:
                self.solve(src, dfs_answer, graph, visited)
        return dfs_answer

if __name__ == "__main__":
    edges = [[0, 1], [0, 2], [1, 2], [1, 3], [1, 4], [2, 5], [3, 4], [3, 5], [6, 7], [7, 8]]
    n = 9
    
    dfs = DFSDisconnectedGraph()
    
    dfs_answer = dfs.depthFirstSearch(edges, n)
    for node in dfs_answer:
        print(node, end=" ")

Javascript Code

class DFSDisconnectedGraph {

    buildGraph(edges, n) {
        const graph = new Array(n).fill(null).map(() => []);
        
        for (const edge of edges) {
            graph[edge[0]].push(edge[1]);
            graph[edge[1]].push(edge[0]);
        }

        return graph;
    }

    solve(node, dfsAnswer, graph, visited) {
        dfsAnswer.push(node);
        visited[node] = true;
        for (const nbr of graph[node]) {
            if (!visited[nbr]) {
                this.solve(nbr, dfsAnswer, graph, visited);
            }
        }
    }

    depthFirstSearch(edges, n) {
        const graph = this.buildGraph(edges, n);
        const dfsAnswer = [];
        const visited = new Array(n).fill(false);
        for (let src = 0; src < n; src++) {
            if (!visited[src]) {
                this.solve(src, dfsAnswer, graph, visited);
            }
        }
        return dfsAnswer;
    }
}

const edges = [[0, 1], [0, 2], [1, 2], [1, 3], [1, 4], [2, 5], [3, 4], [3, 5], [6, 7], [7, 8]];
const n = 9;

const dfs = new DFSDisconnectedGraph();
const dfsAnswer = dfs.depthFirstSearch(edges, n);
console.log(dfsAnswer.join(' '));

Go Code

package main

import "fmt"

type DFSDisconnectedGraph struct{}

func (dfs *DFSDisconnectedGraph) buildGraph(edges [][]int, n int) [][]int {
	graph := make([][]int, n)

	for i := 0; i < n; i++ {
		graph[i] = make([]int, 0)
	}

	for _, edge := range edges {
		graph[edge[0]] = append(graph[edge[0]], edge[1])
		graph[edge[1]] = append(graph[edge[1]], edge[0])
	}

	return graph
}

func (dfs *DFSDisconnectedGraph) solve(node int, dfsAnswer *[]int, graph [][]int, visited []bool) {
	*dfsAnswer = append(*dfsAnswer, node)
	visited[node] = true
	for _, nbr := range graph[node] {
		if !visited[nbr] {
			dfs.solve(nbr, dfsAnswer, graph, visited)
		}
	}
}

func (dfs *DFSDisconnectedGraph) depthFirstSearch(edges [][]int, n int) []int {
	graph := dfs.buildGraph(edges, n)
	dfsAnswer := make([]int, 0)
	visited := make([]bool, n)
	for src := 0; src < n; src++ {
	    if !visited[src] {
	        dfs.solve(src, &dfsAnswer, graph, visited)
	    }
	}
	return dfsAnswer
}

func main() {
	edges := [][]int{{0, 1}, {0, 2}, {1, 2}, {1, 3}, {1, 4}, {2, 5}, {3, 4}, {3, 5}}
	n := 9

	var dfs DFSDisconnectedGraph
	dfsAnswer := dfs.depthFirstSearch(edges, n)
	for _, node := range dfsAnswer {
		fmt.Printf("%d ", node)
	}
}

Complexity Analysis

Time Complexity: O(V + E), where V is the total number of vertices and E is the number of edges.
Space Complexity: O(V + E), where V is the total number of vertices and E is the number of edges.