NewThe Learning module is now liveSee what's new

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 requested status. Otherwise, the task uses the requested status.

  • 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 to add.

  • 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.

Constraints:

  • 1 ≤ taskId.length, description.length ≤ 100
  • Each taskId is unique within the list
  • All string inputs are non-null and non-empty
  • status must 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".

Accepted
461/1.9k
Acceptance Rate24.4%
Test Cases
Input
Output
Expected