Enumerate Directed Paths and Cycles
Reported by candidates from ByteDance's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
ByteDance reported this one in September 2026, and the whole thing hinges on one structure: an adjacency list walked with DFS and a visited set. You need every simple path from start to target, plus every simple directed cycle in the graph, returned as sorted comma-joined strings in two rows. It looks like two problems stapled together. It's really one backtracking template used twice. With at most 12 vertices and 40 edges, brute force is the intended answer. If you blank on the cycle normalization, StealthCoder is the safety net that runs invisibly during the live OA and hands you the working approach.
The problem
You are given a directed graph as an adjacency list and two distinct vertices, start and target. Enumerate: every simple directed path from start to target; and every simple directed cycle anywhere in the graph. A simple path or cycle does not repeat a vertex. A self-loop is a one-vertex cycle. Cycles that differ only by rotation are the same; represent each cycle with its smallest vertex first. Reversing a cycle is not an equivalence because edge direction matters. Return a String[][] with exactly two rows. Row 0 contains the paths and row 1 contains the cycles. Encode each vertex sequence by joining its decimal vertex IDs with commas, without spaces. Sort both rows by lexicographic order of their integer sequences, comparing the first unequal integer and then length when one sequence is a prefix. Function enumeratePathsAndCycles(adjacency: int[][], start: int, target: int) → String[][] Examples Example 1 adjacency = [[1,2],[2,3],[0,3],[]] start = 0 target = 3 return = [["0,1,2,3","0,1,3","0,2,3"],["0,1,2","0,2"]] There are three simple paths from 0 to 3. The graph also contains the normalized cycles 0,1,2 and 0,2. Example 2 adjacency = [[0,1],[2],[1],[]] start = 0 target = 2 return = [["0,1,2"],["0","1,2"]] The path is 0,1,2. The graph also contains the self-loop at 0 and the two-vertex directed cycle 1,2. Example 3 adjacency = [[1],[],[3],[]] start = 0 target = 3 return = [[],[]] The target is unreachable from the start, and the graph contains no directed cycle, so both rows are empty. Constraints 1 <= adjacency.length <= 12. Every neighbor is a vertex ID in [0, adjacency.length - 1]. The graph contains at most 40 directed edges and no duplicate edge. 0 <= start, target < adjacency.length and start != target.
Reported by candidates. Source: FastPrep
Pattern and pitfall
Path enumeration is plain backtracking. Start at start, keep an on-path boolean array, recurse into unvisited neighbors, record the path when you hit target, then unmark on the way back. Cycles use the same DFS with one rule to kill duplicates: for each vertex s as the root, only visit vertices greater than s, and a cycle closes when you see an edge back to s. That makes s the smallest vertex automatically, so rotations never appear twice. Self-loops fall out for free as a one-vertex cycle when s has an edge to s. The pitfalls are sorting and formatting. Sort by integer sequence, not by string, because "10,2" sorts wrong as text. Compare element by element, then by length for prefixes. Empty rows must still be returned. If the sorting comparator trips you mid-assessment, StealthCoder is the hedge that gives you a correct one.
The honest play: practice the pattern, and have StealthCoder ready for the one you didn't see coming.
You can drill Enumerate Directed Paths and Cycles cold, or you can hedge it. StealthCoder runs invisibly during screen share and surfaces a working solution in under 2 seconds. The proctor sees the IDE. They don't see what's behind it. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass ByteDance's OA.
ByteDance reuses patterns across OAs. Built for the candidate who saw this exact problem leak two days before his OA and wondered if anyone had a play. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Enumerate Directed Paths and Cycles FAQ
What's the trick to avoiding duplicate cycles in the ByteDance graph problem?+
Root the DFS at each vertex s and only allow vertices larger than s. A cycle is recorded when a neighbor equals s. This forces the smallest vertex first, so each rotation is generated exactly once. Reversed cycles are different here because edges are directed.
How hard is this problem really?+
Medium on difficulty, high on fiddliness. The algorithm is standard backtracking, and the small limits (12 vertices, 40 edges) mean no pruning is needed. Most lost points come from sorting and output formatting, not from the search.
Why can't I just sort the output strings normally?+
Plain string sorting puts "10,1" before "2,3" because it compares characters, not integers. Store each sequence as an int list, sort with a comparator that checks the first unequal integer then length, and only then join into comma strings.
How are self-loops and unreachable targets handled?+
A self-loop is a one-vertex cycle, so when rooted at s you add "s" if s appears in its own neighbor list. If target is unreachable, the paths row is simply empty. If there are no cycles, that row is empty too. Always return two rows.
How do I prepare for this in 48 hours?+
Write backtracking DFS with a visited array until the undo step is automatic. Then write the smallest-vertex-root cycle enumeration and a custom comparator for int sequences. Test on the three given examples, especially the self-loop case in example 2 and the empty case in example 3.