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;
};
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.
minimum
value.actual
.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.
minimum - actual
. This ensures tasks that require the most "buffer" are done first.energy
to 0. This will track the minimum starting energy needed as we process each task.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
.energy
to be the maximum of energy + actual
and minimum
.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.
Let's use the example tasks = [[1, 3], [2, 4], [10, 11]]
.
minimum - actual
for each:
energy = 0
.energy = 15
.So, the minimum initial energy needed is 15.
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.