You are given an array milestones
where milestones[i]
represents the number of tasks for the i
-th project. Every week, you must work on exactly one task, and you can only work on one project each week.
However, you cannot work on the same project in two consecutive weeks.
Your goal is to determine the maximum number of weeks you can work under these constraints, given that you must always pick a project with remaining tasks, and you cannot work on the same project two weeks in a row.
Constraints:
1 <= milestones.length <= 10^5
1 <= milestones[i] <= 10^9
At first glance, you might try to simulate the process: alternate between projects, always picking one with remaining tasks, and avoid repeating the same project two weeks in a row. However, with large inputs, this brute-force simulation would be too slow.
Instead, let's reason about the constraints. The only rule is that you cannot pick the same project twice in a row. This means that if one project has a huge number of tasks compared to the others, eventually you'll be forced to break the rule because there are not enough other projects to alternate with.
The key insight is to look at the project with the most tasks. If the largest project has more tasks than the sum of all the others plus one, it will be impossible to alternate forever without repeating it. Otherwise, you can alternate freely between projects until all tasks are done.
total = sum(milestones)
.
max_tasks = max(milestones)
.
max_tasks <= total - max_tasks + 1
, you can work all weeks (i.e., finish all tasks) by alternating projects.
total
.2 * (total - max_tasks) + 1
(alternate as much as possible, then do one extra task from the biggest project).This approach is efficient because it only requires a single pass to find the sum and the maximum, and no simulation is needed.
Example Input: milestones = [3, 2, 2]
3 + 2 + 2 = 7
3
2 + 2 = 4
3 <= 4 + 1
→ 3 <= 5
(True)
Example Input 2: milestones = [7, 3, 2]
7 + 3 + 2 = 12
7
3 + 2 = 5
7 <= 5 + 1
→ 7 <= 6
(False)2 * 5 + 1 = 11
O(N * max(milestones))
— not feasible for large inputs.
O(N)
time, where N
is the number of projects).
O(1)
, since we only store a few variables regardless of input size.
The main insight is to recognize that the project with the most tasks can only be alternated as long as there are enough tasks in other projects. If not, you are limited by how many times you can alternate before being forced to repeat the same project. The solution is efficient, requiring only a single pass through the input, and elegantly handles all edge cases with a simple formula.
class Solution:
def numberOfWeeks(self, milestones):
total = sum(milestones)
max_tasks = max(milestones)
if max_tasks <= total - max_tasks + 1:
return total
else:
return 2 * (total - max_tasks) + 1
class Solution {
public:
long long numberOfWeeks(vector<int>& milestones) {
long long total = 0;
int max_tasks = 0;
for (int m : milestones) {
total += m;
max_tasks = max(max_tasks, m);
}
if (max_tasks <= total - max_tasks + 1)
return total;
else
return 2 * (total - max_tasks) + 1;
}
};
class Solution {
public long numberOfWeeks(int[] milestones) {
long total = 0;
int max_tasks = 0;
for (int m : milestones) {
total += m;
max_tasks = Math.max(max_tasks, m);
}
if (max_tasks <= total - max_tasks + 1)
return total;
else
return 2 * (total - max_tasks) + 1;
}
}
var numberOfWeeks = function(milestones) {
let total = milestones.reduce((a, b) => a + b, 0);
let max_tasks = Math.max(...milestones);
if (max_tasks <= total - max_tasks + 1) {
return total;
} else {
return 2 * (total - max_tasks) + 1;
}
};