3457. Eat Pizzas!
Problem Description
You have an integer array pizzas
of size n
, where pizzas[i]
represents the weight of the i-th pizza. You must eat exactly 4 pizzas every day until all pizzas are consumed.
When you eat 4 pizzas with weights W
, X
, Y
, and Z
(where W โค X โค Y โค Z
), you only gain the weight of 1 pizza based on the day:
- On odd-numbered days (days 1, 3, 5, ...), you gain weight
Z
(the maximum weight among the 4 pizzas) - On even-numbered days (days 2, 4, 6, ...), you gain weight
Y
(the second largest weight among the 4 pizzas)
Your goal is to find the maximum total weight you can gain by strategically choosing which 4 pizzas to eat each day.
Constraints:
n
is guaranteed to be a multiple of 4- Each pizza can only be eaten once
- You must eat all pizzas
For example, if you have 8 pizzas, you'll eat for 2 days (4 pizzas each day). On day 1 (odd), you gain the maximum weight from your chosen 4 pizzas. On day 2 (even), you gain the second largest weight from the remaining 4 pizzas.
The challenge is to determine the optimal grouping of pizzas across all days to maximize your total weight gain.
Intuition
To maximize our total weight gain, we need to think about which pizzas should be the "Z" values (for odd days) and which should be the "Y" values (for even days).
Since we always want to maximize our weight gain, let's consider what happens when we sort all pizzas in ascending order. The key insight is that on odd days we get the maximum weight from 4 pizzas, while on even days we get the second largest weight.
If we have days = n/4
total days, we'll have odd = (days + 1) / 2
odd days and even = days - odd
even days.
For odd days, we want the Z values (maximum of each group) to be as large as possible. The best strategy is to take the odd
largest pizzas and make each of them the maximum in their respective groups. We pair each of these large pizzas with 3 of the smallest available pizzas. This way, we ensure that the largest pizzas become our Z values.
For even days, we need the Y values (second largest) to be maximized. After using the largest odd
pizzas for odd days, we look at the remaining pizzas. Among these, we want to select groups where the second largest value is as high as possible. The optimal approach is to take the next largest available pizzas and make them the second largest in their groups by pairing them strategically.
The greedy approach works here: sort the pizzas, allocate the top odd
pizzas for odd days (they'll be the maximum in their groups), then for even days, select pizzas such that the second largest values are maximized. This can be achieved by taking pizzas at positions n - odd - 2
, n - odd - 4
, etc., making them the Y values in their respective groups.
This strategy ensures we're getting the highest possible weights on both odd and even days.
Solution Approach
Let's implement the greedy strategy step by step:
Step 1: Sort the pizzas
pizzas.sort()
We sort the array in ascending order to easily identify the largest and smallest pizzas.
Step 2: Calculate the number of days
days = len(pizzas) // 4
odd = (days + 1) // 2
even = days - odd
Since we eat 4 pizzas per day, we have days = n/4
total days. We calculate how many odd days and even days we have.
Step 3: Handle odd days - maximize Z values
ans = sum(pizzas[-odd:])
For odd days, we want the largest pizzas to be the Z (maximum) values. We take the last odd
pizzas from the sorted array (these are the largest ones) and sum them up. Each of these will be the maximum in their group of 4 pizzas on odd days.
Step 4: Handle even days - maximize Y values
i = len(pizzas) - odd - 2
for _ in range(even):
ans += pizzas[i]
i -= 2
For even days, we need to maximize the Y (second largest) values. After reserving the top odd
pizzas for odd days, we start from position n - odd - 2
(skipping the largest unused pizza at n - odd - 1
).
The pattern here is clever: by taking every other pizza going backwards (positions n - odd - 2
, n - odd - 4
, etc.), we ensure these pizzas become the second largest in their groups. This is because:
- The pizza at position
n - odd - 1
will be the largest in its group - The pizza at position
n - odd - 2
will be the second largest (our Y value) - The remaining two pizzas in the group will come from the smaller pizzas
This greedy allocation ensures we maximize the total weight gain by strategically assigning the heaviest available pizzas to be either Z values (on odd days) or Y values (on even days).
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through an example with 8 pizzas: pizzas = [3, 8, 1, 5, 7, 9, 2, 6]
Step 1: Sort the pizzas
After sorting: [1, 2, 3, 5, 6, 7, 8, 9]
Step 2: Calculate days
- Total days = 8 รท 4 = 2 days
- Odd days = (2 + 1) รท 2 = 1 odd day (day 1)
- Even days = 2 - 1 = 1 even day (day 2)
Step 3: Maximize Z values for odd days
We need 1 pizza to be the maximum (Z) on the odd day. Take the largest pizza: 9
- Running total:
ans = 9
Step 4: Maximize Y values for even days For the 1 even day, we need to maximize the second-largest (Y) value.
- Start at position:
8 - 1 - 2 = 5
(which is pizza with weight7
) - Add pizza at index 5:
ans = 9 + 7 = 16
Verification of groupings: Let's see how the pizzas would be grouped:
- Day 1 (odd): We eat
[1, 2, 3, 9]
โ gain weight =9
(maximum) - Day 2 (even): We eat
[5, 6, 7, 8]
โ gain weight =7
(second largest)
Total weight gained = 9 + 7 = 16
Notice how the strategy ensures:
- The largest pizza (9) becomes the maximum in a group for the odd day
- The pizza at position 5 (weight 7) becomes the second-largest in its group for the even day
- This greedy allocation maximizes our total weight gain
Solution Implementation
1class Solution:
2 def maxWeight(self, pizzas: List[int]) -> int:
3 """
4 Calculate the maximum weight by selecting pizzas using an alternating pattern.
5
6 The strategy:
7 1. Take the total number of days (length of pizzas divided by 4)
8 2. Split days into odd and even counts
9 3. Take the highest weighted pizzas for odd days
10 4. Take alternating pizzas (every other one) for even days
11
12 Args:
13 pizzas: List of pizza weights
14
15 Returns:
16 Maximum total weight achievable
17 """
18 # Calculate the number of days (each day represents 4 pizzas)
19 total_days = len(pizzas) // 4
20
21 # Sort pizzas in ascending order to easily access highest weights
22 pizzas.sort()
23
24 # Calculate odd and even day splits
25 # If total_days is odd, odd_days gets one more than even_days
26 odd_days = (total_days + 1) // 2
27 even_days = total_days - odd_days
28
29 # Start with the sum of the highest 'odd_days' number of pizzas
30 # These are the last 'odd_days' elements after sorting
31 max_weight_sum = sum(pizzas[-odd_days:])
32
33 # Starting position for selecting even day pizzas
34 # Start from 2 positions before the odd_days selection
35 current_index = len(pizzas) - odd_days - 2
36
37 # Add pizzas for even days, selecting every other pizza going backwards
38 for _ in range(even_days):
39 max_weight_sum += pizzas[current_index]
40 current_index -= 2 # Skip one pizza each time
41
42 return max_weight_sum
43
1class Solution {
2 public long maxWeight(int[] pizzas) {
3 int n = pizzas.length;
4
5 // Calculate total number of days (each day consumes 4 pizzas)
6 int days = n / 4;
7
8 // Sort pizzas in ascending order by weight
9 Arrays.sort(pizzas);
10
11 // Calculate number of odd days and even days
12 // For odd days: if days=5, odd=(5+1)/2=3; if days=4, odd=(4+1)/2=2
13 int oddDays = (days + 1) / 2;
14 int evenDays = days / 2;
15
16 // Initialize total weight sum
17 long totalWeight = 0;
18
19 // Add the heaviest 'oddDays' pizzas from the end of sorted array
20 // These represent the maximum weight pizzas selected on odd days
21 for (int i = n - oddDays; i < n; i++) {
22 totalWeight += pizzas[i];
23 }
24
25 // Add pizzas for even days, starting from position (n - oddDays - 2)
26 // and moving backwards by 2 positions each time
27 int currentIndex = n - oddDays - 2;
28 while (evenDays > 0) {
29 totalWeight += pizzas[currentIndex];
30 currentIndex -= 2;
31 evenDays--;
32 }
33
34 return totalWeight;
35 }
36}
37
1class Solution {
2public:
3 long long maxWeight(vector<int>& pizzas) {
4 int n = pizzas.size();
5 int days = n / 4; // Total number of days (each day requires 4 pizzas)
6
7 // Sort pizzas in ascending order by weight
8 ranges::sort(pizzas);
9
10 // Calculate number of odd and even days
11 int oddDays = (days + 1) / 2; // Number of odd-numbered days
12 int evenDays = days - oddDays; // Number of even-numbered days
13
14 // Initialize answer with the sum of the heaviest 'oddDays' pizzas
15 // These will be used for odd-numbered days (where we pick the heaviest)
16 long long totalWeight = accumulate(pizzas.begin() + n - oddDays,
17 pizzas.end(), 0LL);
18
19 // Add pizzas for even-numbered days
20 // Start from position n - oddDays - 2 and pick every other pizza going backwards
21 // This ensures we pick lighter pizzas for even days while avoiding conflicts
22 int currentIndex = n - oddDays - 2;
23 for (int remainingEvenDays = evenDays; remainingEvenDays > 0; --remainingEvenDays) {
24 totalWeight += pizzas[currentIndex];
25 currentIndex -= 2; // Skip one pizza to maintain the pattern
26 }
27
28 return totalWeight;
29 }
30};
31
1/**
2 * Calculates the maximum weight that can be obtained from pizzas
3 * @param pizzas - Array of pizza weights
4 * @returns Maximum total weight achievable
5 */
6function maxWeight(pizzas: number[]): number {
7 // Get the total number of pizzas
8 const n: number = pizzas.length;
9
10 // Calculate the number of days (n divided by 4)
11 const days: number = n >> 2;
12
13 // Sort pizzas in ascending order by weight
14 pizzas.sort((a: number, b: number) => a - b);
15
16 // Calculate the number of odd-indexed selections needed
17 // This is ceiling of (days + 1) / 2
18 const oddSelections: number = (days + 1) >> 1;
19
20 // Calculate the number of even-indexed selections needed
21 let evenSelections: number = days - oddSelections;
22
23 // Initialize the answer to track total weight
24 let totalWeight: number = 0;
25
26 // Add the weights of the heaviest pizzas (odd selections)
27 // Start from position (n - oddSelections) and go to the end
28 for (let i: number = n - oddSelections; i < n; ++i) {
29 totalWeight += pizzas[i];
30 }
31
32 // Add weights for even selections, picking every other pizza
33 // Start from position (n - oddSelections - 2) and move backwards by 2
34 let currentIndex: number = n - oddSelections - 2;
35 while (evenSelections > 0) {
36 totalWeight += pizzas[currentIndex];
37 currentIndex -= 2;
38 evenSelections--;
39 }
40
41 return totalWeight;
42}
43
Time and Space Complexity
The time complexity is O(n ร log n)
, where n
is the length of the array pizzas
. This is dominated by the sorting operation pizzas.sort()
, which uses a comparison-based sorting algorithm (Timsort in Python) that has O(n ร log n)
time complexity. The subsequent operations include:
- Calculating
days
,odd
, andeven
:O(1)
- Slicing to get
pizzas[-odd:]
and summing:O(odd)
which isO(n)
- The for loop that runs
even
times:O(even)
which isO(n)
Since O(n ร log n)
dominates O(n)
, the overall time complexity is O(n ร log n)
.
The space complexity is O(log n)
. Python's Timsort algorithm uses O(log n)
auxiliary space for the sorting operation in the worst case due to the merge operations and the stack used for tracking runs. The other variables (days
, odd
, even
, ans
, i
) use constant space O(1)
. The slicing operation pizzas[-odd:]
creates a new list, but this is used directly in the sum()
function and the space can be considered temporary. Therefore, the dominant space complexity comes from the sorting algorithm, resulting in O(log n)
space complexity.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Index Out of Bounds When Computing Even Days
The Pitfall:
When calculating the starting index for even days as current_index = len(pizzas) - odd_days - 2
, this can become negative if there are too few pizzas or too many odd days. For example, with 4 pizzas (1 day, which is odd), the calculation gives 4 - 1 - 2 = 1
, which works. But edge cases might cause issues if not handled properly.
Solution:
Add a boundary check or ensure the logic handles the case when even_days = 0
:
if even_days > 0:
current_index = len(pizzas) - odd_days - 2
for _ in range(even_days):
max_weight_sum += pizzas[current_index]
current_index -= 2
2. Misunderstanding the Greedy Assignment Pattern
The Pitfall:
Developers might incorrectly assume they should take consecutive pizzas for even days rather than alternating ones. Taking consecutive pizzas (like n-odd-1
, n-odd-2
, n-odd-3
) would result in suboptimal groupings where the second-largest values aren't maximized.
Solution: Ensure the step size is 2 when selecting pizzas for even days. The pattern should be:
- Position
n - odd - 2
(becomes Y in its group) - Position
n - odd - 4
(becomes Y in its group) - And so on...
This ensures each selected pizza can serve as the second-largest in its group of 4.
3. Incorrect Day Count Calculation
The Pitfall:
Using integer division incorrectly or confusing the relationship between odd and even days. For instance, writing odd_days = total_days // 2
instead of odd_days = (total_days + 1) // 2
would give wrong results when total_days is odd.
Solution: Use the ceiling division formula correctly:
odd_days = (total_days + 1) // 2 even_days = total_days - odd_days
This ensures that when total_days is odd (e.g., 3), odd_days gets the extra day (2 odd days, 1 even day).
4. Not Sorting the Array
The Pitfall: Forgetting to sort the pizzas array would completely break the greedy algorithm, as the logic depends on accessing the largest elements from the end of a sorted array.
Solution: Always sort the array first:
pizzas.sort() # Critical - must be sorted for the algorithm to work
5. Off-by-One Error in Loop Iteration
The Pitfall:
When iterating for even days, using range(even_days - 1)
instead of range(even_days)
would miss processing one day's worth of pizzas.
Solution:
Ensure the loop runs exactly even_days
times:
for _ in range(even_days): # Correct: iterates exactly even_days times
max_weight_sum += pizzas[current_index]
current_index -= 2
How many ways can you arrange the three letters A, B and C?
Recommended Readings
Greedy Introduction div class responsive iframe iframe src https www youtube com embed WTslqPbj7I title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture web share allowfullscreen iframe div When do we use greedy Greedy algorithms tend to solve optimization problems Typically they will ask you to calculate the max min of some value Commonly you may see this phrased in the problem as max min longest shortest largest smallest etc These keywords can be identified by just scanning
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Donโt Miss This!