You're given a directed graph and a starting node. Implement depthFirstSearch(graph, start) so it returns an array of nodes in the order depth-first search visits them — diving down one branch all the way to its end before backing up and trying the next branch. The graph is supplied as an adjacency map: a plain object whose keys are node names and whose values are arrays of the names that node points to.
DFS is the counterpart of breadth-first search. Both reach the same set of nodes, but in different orders: BFS sweeps level by level outward from start; DFS commits to one path and walks it to a leaf (or to a node it has already seen) before backing up. You can implement DFS recursively or with an explicit stack — either is fine, as long as the output order matches.
// `graph` is an adjacency map: { node: [neighbor, neighbor, ...] }.
// `start` is the node to begin from.
// Returns the visit order as an array. Each node appears at most once.
function depthFirstSearch(graph: Record<string, string[]>, start: string): string[];
const graph = {
A: ['B', 'C'],
B: ['D'],
C: ['E'],
D: [],
E: [],
};
depthFirstSearch(graph, 'A'); // ['A', 'B', 'D', 'C', 'E']
// Cycle: B points back at A. DFS must not revisit A.
const cyclic = {
A: ['B'],
B: ['C', 'A'],
C: [],
};
depthFirstSearch(cyclic, 'A'); // ['A', 'B', 'C']
// Disconnected: nodes X, Y exist in the map but aren't reachable from A.
const disconnected = {
A: ['B'],
B: [],
X: ['Y'],
Y: [],
};
depthFirstSearch(disconnected, 'A'); // ['A', 'B']
A: ['B', 'C'], B's whole subtree is explored before you touch C.start. Nodes elsewhere in the map do not appear in the output.start is not a key in graph, return [].