Extend the ToDo list system to support task dependencies. A task may depend on one or more parent tasks, and its status may be automatically updated based on the status of those dependencies.
The ToDoList class is modified as follows:
-
void add(String taskId, String description, String status, List<String> dependencies)Adds a task with the given dependencies. If any dependency does not have status"SUCCEEDED", the new task's initial status is set to"BLOCKED"regardless of the requestedstatus. Otherwise, the task uses the requestedstatus. -
List<String> get(String taskId)Returns the task in the format[taskId, description, status, dependency1, dependency2, ...]. The first three elements are the task ID, description, and current status. The remaining elements are the task's dependency IDs in the same order as they were provided toadd. -
void updateStatus(String taskId, String newStatus)Updates the task's status and propagates the change to tasks that depend on it.- If a task changes to
"SUCCEEDED", each blocked dependent task checks whether all of its dependencies now have status"SUCCEEDED". If so, that dependent task changes from"BLOCKED"to"READY". - If a task changes to
"FAILED", each task that depends on it is marked as"FAILED", and this failure propagates recursively to tasks that depend on those failed tasks.
- If a task changes to
Constraints:
- 1 ≤
taskId.length,description.length≤ 100 - Each
taskIdis unique within the list - All string inputs are non-null and non-empty
statusmust be one of:"READY","IN_PROGRESS","SUCCEEDED","FAILED","BLOCKED"- Dependency task IDs in the input list must refer to tasks already added to the system
- The dependency graph is guaranteed to be acyclic
- The number of operations will not exceed 104
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:
ToDoList todoList = new ToDoList();todoList.add("task1", "Prepare data", "READY", []);// Add task "task1" with no dependencies and status "READY".todoList.add("task2", "Train model", "READY", ["task1"]);// Add task "task2" depending on "task1". Since "task1" is not yet "SUCCEEDED", "task2" is set to "BLOCKED".todoList.add("task3", "Deploy model", "READY", ["task2"]);// Add task "task3" depending on "task2". Since "task2" is not yet "SUCCEEDED", "task3" is set to "BLOCKED".todoList.add("task4", "Monitor", "READY", ["task3"]);// Add task "task4" depending on "task3". Since "task3" is not yet "SUCCEEDED", "task4" is set to "BLOCKED".todoList.updateStatus("task1", "SUCCEEDED");// Update "task1" to "SUCCEEDED". This causes "task2" to transition from "BLOCKED" to "READY" since all its dependencies are now succeeded.todoList.get("task2");// Returns ["task2", "Train model", "READY", "task1"]. Task "task2" is now "READY".todoList.updateStatus("task2", "SUCCEEDED");// Update "task2" to "SUCCEEDED". This causes "task3" to transition from "BLOCKED" to "READY".todoList.get("task3");// Returns ["task3", "Deploy model", "READY", "task2"]. Task "task3" is now "READY".
