Critical Path Through Dependent Tasks
Reported by candidates from Modular's online assessment. Pattern, common pitfall, and the honest play if you blank under the timer.
Modular sent this one around in April 2026, and it looks fancier than it is. Strip the task-name story and it's the longest weighted path in a DAG, with a lexicographic tiebreak bolted on. Nodes carry the weight, not edges. You return the total duration first, then the task names in execution order. With n capped at 200, you don't need anything clever, you need clean bookkeeping. If you blank mid-assessment, StealthCoder runs invisibly on screen and can hand you the structure. Here's the shape of the answer so you don't need it.
The problem
Each task has a unique name, a positive duration, and zero or more prerequisite task names. The dependencies form a directed acyclic graph. Return a string array whose first value is the maximum total duration of any dependency path and whose remaining values are the task names on that path in execution order. If several paths have the same maximum duration, return the lexicographically smallest task-name sequence. Function criticalPathSchedule(taskNames: String[], dependencies: String[][], durations: int[]) → String[] Examples Example 1 taskNames = ["A","B","C"] dependencies = [[],[],["A"]] durations = [3,5,5] return = ["8","A","C"] The dependent path A to C lasts 8, longer than standalone B. Example 2 taskNames = ["A","B","C","D","E"] dependencies = [[],["A"],["A"],["B","C"],["D"]] durations = [3,2,7,4,2] return = ["16","A","C","D","E"] The longer branch into D passes through C. Example 3 taskNames = ["A","B"] dependencies = [[],[]] durations = [4,4] return = ["4","A"] Equal standalone paths use the lexicographically smaller sequence. Constraints 1 <= taskNames.length == dependencies.length == durations.length <= 200. Task names are unique nonempty ASCII strings. Every dependency names another task, and the graph is acyclic. 1 <= durations[i] <= 100000; every path total fits a signed 32-bit integer.
Reported by candidates. Source: FastPrep
Pattern and pitfall
Topologically sort the tasks, or memoize a DFS. Define best[v] as the max total duration of a path that ends at v, and keep the best path itself as a list. For each task, look at all its prerequisites, pick the one with the largest best[], then add the task's own duration. The trap is the tiebreak. When two prerequisites give equal totals, compare the full name sequences lexicographically, not just the last name. With 200 nodes you can store whole paths and compare them as lists. Finally, scan all end nodes, take the max total, and break ties by comparing paths. Compare sequences element by element, not as joined strings, since names can differ in length. A prefix sequence is smaller than a longer one, but with equal totals and positive durations that rarely matters. StealthCoder is the hedge if the tiebreak logic slips under the clock.
If you see this problem in your OA tomorrow, the play is to recognize the pattern in 30 seconds. StealthCoder buys you that recognition.
You can drill Critical Path Through Dependent Tasks 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 by an Amazon engineer who passed his OA cold and still thinks the filter is broken.
Get StealthCoderRelated leaked OAs
You've seen the question.
Make sure you actually pass Modular's OA.
Modular reuses patterns across OAs. Built by an Amazon engineer who passed his OA cold and still thinks the filter is broken. Works on HackerRank, CodeSignal, CoderPad, and Karat.
Critical Path Through Dependent Tasks FAQ
What's the core trick in Critical Path Through Dependent Tasks?+
It's longest path in a DAG with node weights. Process tasks in topological order, or memoize DFS, and compute the best path ending at each task. Then take the best across all tasks. The lexicographic tiebreak is the only real wrinkle, and it's handled by comparing stored paths.
How do I handle ties on duration?+
Store the full path for each task's best result. When two candidates have equal totals, compare the name sequences element by element and keep the smaller one. Do this at every task and again when picking the final end node. Comparing only the last name is the classic mistake.
Is the greedy approach safe here?+
Not by itself. Picking the biggest prerequisite works for totals, but ties force you to compare whole sequences. Because the path is built from the start, the lexicographically smallest full sequence must be chosen carefully, so keep paths rather than just numbers.
How hard is this really for an OA?+
Medium. The graph is small at 200 nodes, so complexity isn't the issue. Most failures come from parsing the dependency lists, mapping names to indexes, and getting the tiebreak right. If you've done longest path in a DAG before, it's straightforward.
How do I prepare in 48 hours?+
Write topological sort with Kahn's algorithm once, then write the DP over it with path reconstruction. Test against the three examples, especially the equal-duration case returning A. Add a test where tied prerequisites lead to different name sequences. That covers nearly every failure mode.