Facebook Pixel

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.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

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.

Learn more about Greedy and Sorting patterns.

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 Evaluator

Example 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 weight 7)
  • 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, and even: O(1)
  • Slicing to get pizzas[-odd:] and summing: O(odd) which is O(n)
  • The for loop that runs even times: O(even) which is O(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
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

How many ways can you arrange the three letters A, B and C?


Recommended Readings

Want a Structured Path to Master System Design Too? Donโ€™t Miss This!

Load More