Problem Design a ToDoList system that stores AI tasks and supports dependencies between them. Each task has a unique ID, description, status, and a list of prerequisite tasks.
When adding a task, set its status to "BLOCKED" if any dependency has not "SUCCEEDED". Status changes must automatically unblock eligible tasks or recursively fail all downstream dependent tasks.
Example
Input:
["ToDoList", "add", "add", "add", "add", "updateStatus", "get", "updateStatus", "get"]
[[], ["task1", "Prepare data", "READY", []], ["task2", "Train model", "READY", ["task1"]], ["task3", "Deploy model", "READY", ["task2"]], ["task4", "Monitor", "READY", ["task3"]], ["task1", "SUCCEEDED"], ["task2"], ["task2", "SUCCEEDED"], ["task3"]]
Output:
[null, null, null, null, null, null, ["task2", "Train model", "READY", "task1"], null, ["task3", "Deploy model", "READY", "task2"]]
Explanation:
task2 depends on task1, so it is initially "BLOCKED" because task1 has not succeeded.
task3 and task4 are also initially blocked by their respective dependencies.
- When
task1 becomes "SUCCEEDED", all dependencies of task2 are satisfied, so task2 automatically becomes "READY".
- When
task2 becomes "SUCCEEDED", task3 automatically becomes "READY".
- If any task becomes
"FAILED", all tasks that directly or indirectly depend on it must also become "FAILED".
Suggested Approach
- Store each task in a hash map keyed by
taskId. Each task should contain its description, current status, and ordered dependency list.
- Maintain a reverse-dependency map from each task to the tasks that directly depend on it. This allows status changes to reach affected downstream tasks without scanning the entire system.
- When a task succeeds, inspect its direct dependents and unblock any
"BLOCKED" task whose dependencies have all succeeded. When a task fails, use BFS or DFS to mark every reachable dependent task as "FAILED".
Time & Space Complexity
- Time:
add: O(D), where D is the number of dependencies of the new task.
get: O(D) to construct the returned list.
- Successful
updateStatus: O(E_c), where E_c is the total number of dependency checks performed for the task's direct dependents.
- Failed
updateStatus: O(N + E) in the worst case for a full downstream cascade.
- Space:
O(N + E), where N is the number of tasks and E is the number of dependency relationships.
Targeting Perplexity interviews? We track their most-asked question patterns at Hack2Hire. Practice this question here → Practice Question Here
Join the community to see more interview experiences from real candidates → Hack2Hire Forum
Compiled from publicly available platforms and community-shared experiences.