My first instinct was just DFS and mark visited nodes, which completely falls apart once you think about cycles for more than thirty seconds.
Model the problem as finding nodes that are not part of any cycle and from which all paths lead to terminal nodes. Use a reverse graph and topological sorting (Kahn's algorithm) to iteratively remove nodes that have outgoing edges to unsafe nodes, starting from terminal nodes. The remaining nodes are safe; return them sorted.
Pro tip: Clarify edge cases upfront: empty graph, self-loops, and disconnected components. Mention that the solution is essentially finding nodes that can reach a terminal node without entering a cycle, which is equivalent to nodes not in any cycle that can reach a terminal.
A node is safe if every path starting from it eventually reaches a terminal node (out-degree 0). This means the node cannot be part of a cycle and all its descendants must also be safe.
Build the reverse graph and compute out-degrees in the original graph. Use a queue to process nodes with out-degree 0 (terminal nodes) and iteratively remove edges from their predecessors, adding new terminal nodes to the queue.
Initialize a queue with all nodes having out-degree 0. While the queue is not empty, pop a node, mark it safe, and for each predecessor in the reverse graph, decrement its out-degree; if it becomes 0, add it to the queue.
After processing, all nodes marked safe are the answer. Collect them and sort in ascending order to meet the output requirement.
Time complexity is O(V+E) and space O(V+E). Test with graphs containing cycles, self-loops, multiple components, and no terminal nodes.
AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.