Minimum Initial Energy to Finish Tasks

hard greedy sorting array

Problem

Each task is [actual, minimum]: actual energy is spent to finish it, but you need at least minimum energy on hand to begin it (with actual ≤ minimum). You may finish tasks in any order. Return the minimum initial energy needed to complete every task.

Inputtasks = [[1,2],[2,4],[4,8]]
Output8
Start with 8. Do [4,8] (need 8, have 8 → 4 left), then [2,4] (→ 2), then [1,2] (→ 1). Starting with 7 fails: you could never begin [4,8].

def minimumEffort(tasks):
    # Do tasks with the smallest slack (minimum - actual) first;
    # the big "reservation gap" tasks are best saved for last.
    tasks.sort(key=lambda t: t[1] - t[0])
    energy = 0                      # min energy needed so far
    for actual, minimum in tasks:
        # After this task we must still hold `energy`, so before it
        # we need energy + actual; we must also clear the `minimum` bar.
        energy = max(energy + actual, minimum)
    return energy
function minimumEffort(tasks) {
  // Do tasks with the smallest slack (minimum - actual) first;
  // the big "reservation gap" tasks are best saved for last.
  tasks.sort((a, b) => (a[1] - a[0]) - (b[1] - b[0]));
  let energy = 0;                  // min energy needed so far
  for (const [actual, minimum] of tasks) {
    // After this task we must still hold `energy`, so before it
    // we need energy + actual; we must also clear the `minimum` bar.
    energy = Math.max(energy + actual, minimum);
  }
  return energy;
}
int minimumEffort(int[][] tasks) {
    // Do tasks with the smallest slack (minimum - actual) first;
    // the big "reservation gap" tasks are best saved for last.
    Arrays.sort(tasks, (a, b) -> (a[1] - a[0]) - (b[1] - b[0]));
    int energy = 0;                 // min energy needed so far
    for (int[] t : tasks) {
        // Before the task we need energy + actual to keep the
        // reserve, and must also clear the `minimum` bar.
        energy = Math.max(energy + t[0], t[1]);
    }
    return energy;
}
int minimumEffort(vector<vector<int>>& tasks) {
    // Do tasks with the smallest slack (minimum - actual) first;
    // the big "reservation gap" tasks are best saved for last.
    sort(tasks.begin(), tasks.end(), [](auto& a, auto& b) {
        return (a[1] - a[0]) < (b[1] - b[0]);
    });
    int energy = 0;                 // min energy needed so far
    for (auto& t : tasks) {
        // Before the task we need energy + actual to keep the
        // reserve, and must also clear the `minimum` bar.
        energy = max(energy + t[0], t[1]);
    }
    return energy;
}
Time: O(n log n) Space: O(1) extra (in-place sort)