Finish Time of Tasks I - Video Solutions
Leetcode 3965 | Finish Time of Tasks I | Clear Explanation | Leetcode biweekly contest 185
Finish Time of Tasks I - Video Solution
Watch 5 video solutions for Finish Time of Tasks I, a medium level problem involving Array, Dynamic Programming, Tree. This walkthrough by CodeWithMeGuys has 136 views views. Want to try solving it yourself? Practice on FleetCode or read the detailed text solution.
Problem Statement
You are given an integer n representing the number of tasks in a project, numbered from 0 to n - 1. These tasks are connected as a tree rooted at task 0. This is represented by a 2D integer array edges of length n - 1, where edges[i] = [ui, vi] indicates that task ui is the parent of task vi.
You are also given an array baseTime of length n, where baseTime[i] represents the time to complete task i.
The finish time of each task is calculated as follows:
- Leaf task: The finish time is
baseTime[i]. - Non-leaf task:
- Let
earliestbe the minimum finish time among its children, andlatestbe the maximum finish time among its children. - Let
ownDurationbe(latest - earliest) + baseTime[i]. - The finish time of task
iislatest + ownDuration.
- Let
Return the finish time of the root task 0.
Example 1:
Input: n = 3, edges = [[0,1],[1,2]], baseTime = [9,5,3]
Output: 17
Explanation:
- Task 2 is a leaf, so its finish time is
baseTime[2] = 3. - Task 1 has one child task 2:
earliest = latest = 3ownDuration = (latest - earliest) + baseTime[1] = 5- Finish time of task 1 is
3 + 5 = 8
- Task 0 has one child with finish time 8:
earliest = latest = 8ownDuration = (latest - earliest) + baseTime[0] = 9- Finish time of task 0 is
8 + 9 = 17
Example 2:
Input: n = 3, edges = [[0,1],[0,2]], baseTime = [4,7,6]
Output: 12
Explanation:
- Task 1 is a leaf, so its finish time is
baseTime[1] = 7. - Task 2 is a leaf, so its finish time is
baseTime[2] = 6. - Task 0 has two children with finish times 7 and 6:
earliest = 6,latest = 7ownDuration = (latest - earliest) + baseTime[0] = (7 - 6) + 4 = 5- Finish time of task 0 is
latest + ownDuration = 7 + 5 = 12
Example 3:
Input: n = 4, edges = [[0,1],[0,2],[2,3]], baseTime = [5,8,2,1]
Output: 18
Explanation:
- Task 1 is a leaf, so its finish time is
baseTime[1] = 8. - Task 3 is a leaf, so its finish time is
baseTime[3] = 1. - Task 2 has one child task 3:
earliest = latest = 1ownDuration = (latest - earliest) + baseTime[2] = 0 + 2 = 2- Finish time of task 2 is
latest + ownDuration = 1 + 2 = 3
- Task 0 has two children with finish times 8 and 3:
earliest = 3,latest = 8ownDuration = (latest - earliest) + baseTime[0] = (8 - 3) + 5 = 10- Finish time of task 0 is
latest + ownDuration = 8 + 10 = 18
Constraints:
1 <= n <= 105edges.length = n - 1edges[i] == [ui, vi]0 <= ui, vi <= n - 1ui != vi- The input is generated such that
edgesrepresents a valid tree. baseTime.length == n1 <= baseTime[i] <= 105βββββββ
Approach Overview
Problem Overview: You are given tasks with a start time and a processing duration. Only one task can run at a time. If the processor is idle, it waits for the next taskβs start time; otherwise the task starts when the previous one finishes. The goal is to compute the exact finish time for each task.
Approach 1: Time Simulation (Brute Force) (Time: O(T), Space: O(1))
The most literal way is to simulate time unit by unit. Maintain a pointer to the current task and increment a global clock. When the clock reaches a taskβs start time, begin processing it and keep advancing the clock until its duration completes. Record the finish time, then move to the next task. This works but becomes inefficient if time values are large because the algorithm iterates across every intermediate timestamp. It demonstrates the mechanics clearly but is rarely acceptable in interviews.
Approach 2: Greedy Running Clock (Optimal) (Time: O(n), Space: O(1))
Instead of advancing time step by step, jump directly to meaningful events. Track a variable currentTime representing when the processor becomes free. For each task, compute its actual start time as max(currentTime, start[i]). The finish time is startActual + duration[i]. Update currentTime to this finish time and continue. This greedy simulation works because tasks are processed in order and the machine can only handle one job at a time, so the only state that matters is when the previous task finished.
This approach effectively compresses idle periods and processing intervals into a single calculation. Each task requires constant work: a comparison, addition, and assignment. The result is linear time with constant extra memory, making it suitable even when the number of tasks is large.
Conceptually this falls under greedy algorithms and simulation. The input handling typically uses simple array traversal, and no auxiliary data structures are required.
Recommended for interviews: The greedy running clock approach. Interviewers expect you to recognize that explicit time simulation is unnecessary. Showing the brute-force idea first demonstrates understanding of the system behavior, while the O(n) event-based simulation shows the optimization skill they are actually evaluating.
Complexity Analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Time Simulation (Brute Force) | O(T) | O(1) | Useful for understanding the process or when timestamps are very small |
| Greedy Running Clock | O(n) | O(1) | General case; optimal solution for large task lists |