{x}
blog image

Maximum Number of Weeks for Which You Can Work

There are n projects numbered from 0 to n - 1. You are given an integer array milestones where each milestones[i] denotes the number of milestones the ith project has.

You can work on the projects following these two rules:

  • Every week, you will finish exactly one milestone of one project. You must work every week.
  • You cannot work on two milestones from the same project for two consecutive weeks.

Once all the milestones of all the projects are finished, or if the only milestones that you can work on will cause you to violate the above rules, you will stop working. Note that you may not be able to finish every project's milestones due to these constraints.

Return the maximum number of weeks you would be able to work on the projects without violating the rules mentioned above.

 

Example 1:

Input: milestones = [1,2,3]
Output: 6
Explanation: One possible scenario is:
​​​​- During the 1st week, you will work on a milestone of project 0.
- During the 2nd week, you will work on a milestone of project 2.
- During the 3rd week, you will work on a milestone of project 1.
- During the 4th week, you will work on a milestone of project 2.
- During the 5th week, you will work on a milestone of project 1.
- During the 6th week, you will work on a milestone of project 2.
The total number of weeks is 6.

Example 2:

Input: milestones = [5,2,1]
Output: 7
Explanation: One possible scenario is:
- During the 1st week, you will work on a milestone of project 0.
- During the 2nd week, you will work on a milestone of project 1.
- During the 3rd week, you will work on a milestone of project 0.
- During the 4th week, you will work on a milestone of project 1.
- During the 5th week, you will work on a milestone of project 0.
- During the 6th week, you will work on a milestone of project 2.
- During the 7th week, you will work on a milestone of project 0.
The total number of weeks is 7.
Note that you cannot work on the last milestone of project 0 on 8th week because it would violate the rules.
Thus, one milestone in project 0 will remain unfinished.

 

Constraints:

  • n == milestones.length
  • 1 <= n <= 105
  • 1 <= milestones[i] <= 109

Solution Explanation:

This problem asks for the maximum number of weeks you can work on projects given constraints on working on milestones. The key insight is to use a greedy approach. We don't need to simulate the process of working week by week; instead, we can determine the maximum number of weeks directly based on the distribution of milestones.

Core Idea:

The maximum number of weeks is limited by two factors:

  1. Total milestones: The sum of milestones across all projects represents the total number of tasks.
  2. Largest project: The project with the maximum number of milestones can potentially restrict the total weeks. If this largest project has significantly more milestones than the rest combined, it will limit the total possible work weeks.

Algorithm:

  1. Calculate total milestones (s): Sum up all the milestones in the milestones array.
  2. Find maximum milestones (mx): Find the largest number of milestones in a single project.
  3. Calculate remaining milestones (rest): Subtract the maximum milestones from the total milestones (s - mx). This represents the total milestones in all other projects.
  4. Check the limiting condition: If mx (milestones in the largest project) is greater than rest + 1, then the largest project's milestones will be limiting factor. In this case, we can complete all milestones in other projects and then almost all milestones in the largest project (all except one). The maximum weeks in this scenario is rest * 2 + 1.
  5. Otherwise: If mx <= rest + 1, then we can complete all milestones, and the maximum number of weeks is simply the total number of milestones (s).

Time and Space Complexity:

  • Time Complexity: O(n), where n is the number of projects. This is because finding the sum and maximum element in the array takes linear time.
  • Space Complexity: O(1). The algorithm uses a constant amount of extra space to store variables.

Code Implementation in Different Languages:

Python3:

class Solution:
    def numberOfWeeks(self, milestones: List[int]) -> int:
        mx, s = max(milestones), sum(milestones)
        rest = s - mx
        return rest * 2 + 1 if mx > rest + 1 else s
 

Java:

class Solution {
    public long numberOfWeeks(int[] milestones) {
        int mx = 0;
        long s = 0;
        for (int e : milestones) {
            s += e;
            mx = Math.max(mx, e);
        }
        long rest = s - mx;
        return mx > rest + 1 ? rest * 2 + 1 : s;
    }
}

C++:

class Solution {
public:
    long long numberOfWeeks(vector<int>& milestones) {
        int mx = *max_element(milestones.begin(), milestones.end());
        long long s = accumulate(milestones.begin(), milestones.end(), 0LL);
        long long rest = s - mx;
        return mx > rest + 1 ? rest * 2 + 1 : s;
    }
};

Go:

func numberOfWeeks(milestones []int) int64 {
	mx := slices.Max(milestones)
	s := 0
	for _, x := range milestones {
		s += x
	}
	rest := s - mx
	if mx > rest+1 {
		return int64(rest*2 + 1)
	}
	return int64(s)
}

TypeScript:

function numberOfWeeks(milestones: number[]): number {
    const mx = Math.max(...milestones);
    const s = milestones.reduce((a, b) => a + b, 0);
    const rest = s - mx;
    return mx > rest + 1 ? rest * 2 + 1 : s;
}

All these code snippets implement the same greedy algorithm, differing only in syntax and standard library functions used for finding the maximum and sum of elements. They all achieve the optimal time and space complexity.