Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1665. Minimum Initial Energy to Finish Tasks - Leetcode Solution

Code Implementation

class Solution:
    def minimumEffort(self, tasks):
        # Sort tasks by (minimum - actual) descending
        tasks.sort(key=lambda x: x[1] - x[0], reverse=True)
        energy = 0
        for actual, minimum in tasks:
            energy = max(energy + actual, minimum)
        return energy
      
class Solution {
public:
    int minimumEffort(vector<vector<int>>& tasks) {
        sort(tasks.begin(), tasks.end(), [](const vector<int>& a, const vector<int>& b) {
            return (a[1] - a[0]) > (b[1] - b[0]);
        });
        int energy = 0;
        for (const auto& task : tasks) {
            energy = max(energy + task[0], task[1]);
        }
        return energy;
    }
};
      
import java.util.*;
class Solution {
    public int minimumEffort(int[][] tasks) {
        Arrays.sort(tasks, (a, b) -> (b[1] - b[0]) - (a[1] - a[0]));
        int energy = 0;
        for (int[] task : tasks) {
            energy = Math.max(energy + task[0], task[1]);
        }
        return energy;
    }
}
      
var minimumEffort = function(tasks) {
    tasks.sort((a, b) => (b[1] - b[0]) - (a[1] - a[0]));
    let energy = 0;
    for (const [actual, minimum] of tasks) {
        energy = Math.max(energy + actual, minimum);
    }
    return energy;
};
      

Problem Description

You are given a list of tasks, where each task is represented as a pair [actual, minimum]. Here, actual is the actual energy cost to complete the task, and minimum is the minimum energy required to start the task.

You can complete the tasks in any order. Your goal is to determine the minimum initial energy required so that you can finish all tasks in some order, never running out of energy at any step.

  • Each task can be used only once.
  • There is always at least one valid solution.
  • You cannot start a task unless your current energy is at least its minimum value.
  • After completing a task, your energy decreases by actual.

Thought Process

At first glance, it might seem that we need to try all permutations of tasks to find the order requiring the least initial energy. This brute-force method would be too slow for large inputs.

To optimize, let's think about what makes a task "hard": if a task's minimum is much larger than its actual cost, it requires a high starting energy, but doesn't reduce your energy by much. These "demanding" tasks should probably be done first.

The key insight is to process the most "demanding" tasks (where minimum - actual is largest) first. By doing so, we minimize the risk of running out of energy before a high-minimum task. This leads us to sort the tasks by minimum - actual in descending order.

Solution Approach

  • Step 1: Sort the tasks in descending order of minimum - actual. This ensures tasks that require the most "buffer" are done first.
  • Step 2: Initialize a variable energy to 0. This will track the minimum starting energy needed as we process each task.
  • Step 3: For each task in the sorted list:
    • If current energy plus the task's actual cost is less than the task's minimum, we need to "bump up" our starting energy to at least minimum.
    • Update energy to be the maximum of energy + actual and minimum.
  • Step 4: After processing all tasks, energy contains the minimum initial energy needed to complete all tasks in some order.

This greedy approach works because it always ensures we have enough energy to start the hardest remaining task, and never wastes extra energy on easier ones.

Example Walkthrough

Let's use the example tasks = [[1, 3], [2, 4], [10, 11]].

  1. Compute minimum - actual for each:
    • [1, 3]: 3 - 1 = 2
    • [2, 4]: 4 - 2 = 2
    • [10, 11]: 11 - 10 = 1
  2. Sort: [[1, 3], [2, 4], [10, 11]] (first two are tied, order doesn't matter).
  3. Initialize energy = 0.
  4. Process [1, 3]:
    • energy + actual = 0 + 1 = 1; minimum = 3
    • Update energy = max(1, 3) = 3
  5. Process [2, 4]:
    • energy + actual = 3 + 2 = 5; minimum = 4
    • Update energy = max(5, 4) = 5
  6. Process [10, 11]:
    • energy + actual = 5 + 10 = 15; minimum = 11
    • Update energy = max(15, 11) = 15
  7. Final answer: energy = 15.

So, the minimum initial energy needed is 15.

Time and Space Complexity

  • Brute-force approach: Trying all permutations is O(n!) time, which is infeasible for large n.
  • Optimized approach:
    • Sorting the tasks: O(n log n)
    • Single pass through the tasks: O(n)
    • Total time complexity: O(n log n)
    • Space complexity: O(1) extra (if sorting in-place), O(n) if not.

Summary

The problem asks for the minimum initial energy needed to finish all tasks in any order, given each task's cost and required starting energy. By sorting tasks to handle the most "demanding" ones first, we use a greedy approach that guarantees we never run out of energy at a critical moment. This strategy is both efficient and elegant, reducing the problem from factorial to logarithmic time complexity.