Unit 11 Session 2 Advanced (Click for link to problem statements)
Understand what the interviewer is asking for by using test cases and questions about the problem.
- Established a set (2-3) of test cases to verify their own solution later.
- Established a set (1-2) of edge cases to verify their solution handles complexities.
- Have fully understood the problem and have no clarifying questions.
- Have you verified any Time/Space Constraints for this problem?
prerequisites[i] = [task_a, task_b]
means that task_b must be completed before task_a.HAPPY CASE
Input: tasks = [""set_table"", ""prepare_dessert""], prerequisites = [[""prepare_dessert"", ""set_table""]]
Output: [""set_table"", ""prepare_dessert""]
Explanation: You need to set the table before you can prepare dessert.
EDGE CASE
Input: tasks = [""only_task""], prerequisites = []
Output: [""only_task""]
Explanation: There's only one task, so no ordering is required.
Match what this problem looks like to known categories of problems, e.g. Linked List or Dynamic Programming, and strategies or patterns in those categories.
For Task Scheduling with Dependencies, we want to consider the following approaches:
Plan the solution with appropriate visualizations and pseudocode.
General Idea: Use topological sort (BFS) to determine the order of tasks. Start with tasks that have no dependencies (in-degree 0) and remove dependencies as tasks are completed.
1) Initialize a graph (adjacency list) and an in-degree map to track dependencies.
2) For each prerequisite, update the graph and increment the in-degree of the dependent task.
3) Use a queue to keep track of tasks with no dependencies (in-degree 0).
4) While the queue is not empty:
a) Remove a task from the queue, add it to the result.
b) Reduce the in-degree of its dependent tasks.
c) If a task's in-degree becomes 0, add it to the queue.
5) If the result contains all tasks, return the result. Otherwise, return an empty array (circular dependency detected).
⚠️ Common Mistakes
Implement the code to solve the algorithm.
from collections import deque
# Function to determine task order for banquet preparation
def prepare_banquet(tasks, prerequisites):
# Step 1: Initialize graph and in-degree map
graph = {task: [] for task in tasks}
in_degree = {task: 0 for task in tasks}
# Step 2: Build the graph and update in-degrees
for task_a, task_b in prerequisites:
graph[task_b].append(task_a) # task_b must be done before task_a
in_degree[task_a] += 1
# Step 3: Find all tasks with in-degree 0 (no dependencies)
queue = deque([task for task in tasks if in_degree[task] == 0])
# Step 4: Perform topological sort
order = []
while queue:
current_task = queue.popleft()
order.append(current_task)
# Decrease the in-degree of all dependent tasks
for neighbor in graph[current_task]:
in_degree[neighbor] -= 1
if in_degree[neighbor] == 0:
queue.append(neighbor)
# Step 5: If the result contains all tasks, return the order. Otherwise, return an empty list.
if len(order) == len(tasks):
return order
else:
return []
Review the code by running specific example(s) and recording values (watchlist) of your code's variables along the way.
Example 1:
Evaluate the performance of your algorithm and state any strong/weak or future potential work.
Assume V
is the number of tasks and E
is the number of dependencies.
O(V + E)
because we process each task and dependency once.O(V + E)
due to the graph representation and in-degree tracking.