Maximum Profit of Operating a Centennial Wheel
MedPrompt
You are the operator of a Centennial Wheel that has four gondolas, and each gondola has room for up to four people. You have the ability to rotate the gondolas counterclockwise, which costs you runningCost dollars.
You are given an array customers of length n where customers[i] is the number of new customers arriving just before the ith rotation (0-indexed). This means you must rotate the wheel i times before the customers[i] customers arrive. You cannot make customers wait if there is room in the gondola. Each customer pays boardingCost dollars when they board on the gondola closest to the ground and will exit once that gondola reaches the ground again.
You can stop the wheel at any time, including before serving all customers. If you decide to stop serving customers, all subsequent rotations are free in order to get all the customers down safely. Note that if there are currently more than four customers waiting at the wheel, only four will board the gondola, and the rest will wait for the next rotation.
Return the minimum number of rotations you need to perform to maximize your profit. If there is no scenario where the profit is positive, return -1.
Example 1:
Input: customers = [8,3], boardingCost = 5, runningCost = 6
Output: 3
Explanation: The numbers written on the gondolas are the number of people currently there.
1. 8 customers arrive, 4 board and 4 wait for the next gondola, the wheel rotates. Current profit is 4 * $5 - 1 * $6 = $14.
2. 3 customers arrive, the 4 waiting board the wheel and the other 3 wait, the wheel rotates. Current profit is 8 * $5 - 2 * $6 = $28.
3. The final 3 customers board the gondola, the wheel rotates. Current profit is 11 * $5 - 3 * $6 = $37.
The highest profit was $37 after rotating the wheel 3 times.Example 2:
Input: customers = [10,9,6], boardingCost = 6, runningCost = 4
Output: 7
Explanation:
1. 10 customers arrive, 4 board and 6 wait for the next gondola, the wheel rotates. Current profit is 4 * $6 - 1 * $4 = $20.
2. 9 customers arrive, 4 board and 11 wait (2 originally waiting, 9 newly waiting), the wheel rotates. Current profit is 8 * $6 - 2 * $4 = $40.
3. The final 6 customers arrive, 4 board and 13 wait, the wheel rotates. Current profit is 12 * $6 - 3 * $4 = $60.
4. 4 board and 9 wait, the wheel rotates. Current profit is 16 * $6 - 4 * $4 = $80.
5. 4 board and 5 wait, the wheel rotates. Current profit is 20 * $6 - 5 * $4 = $100.
6. 4 board and 1 waits, the wheel rotates. Current profit is 24 * $6 - 6 * $4 = $120.
7. 1 boards, the wheel rotates. Current profit is 25 * $6 - 7 * $4 = $122.
The highest profit was $122 after rotating the wheel 7 times.Example 3:
Input: customers = [3,4,0,5,1], boardingCost = 1, runningCost = 92
Output: -1
Explanation:
1. 3 customers arrive, 3 board and 0 wait, the wheel rotates. Current profit is 3 * $1 - 1 * $92 = -$89.
2. 4 customers arrive, 4 board and 0 wait, the wheel rotates. Current profit is 7 * $1 - 2 * $92 = -$177.
3. 0 customers arrive, 0 board and 0 wait, the wheel rotates. Current profit is 7 * $1 - 3 * $92 = -$269.
4. 5 customers arrive, 4 board and 1 waits, the wheel rotates. Current profit is 11 * $1 - 4 * $92 = -$357.
5. 1 customer arrives, 2 board and 0 wait, the wheel rotates. Current profit is 13 * $1 - 5 * $92 = -$447.
The profit was never positive, so return -1.
Constraints:
n == customers.length1 <= n <= 1050 <= customers[i] <= 501 <= boardingCost, runningCost <= 100
Approaches
2 approaches with complexity analysis and trade-offs.
This approach directly simulates the process described in the problem. We maintain the number of waiting customers, the current profit, and the number of rotations. We iterate rotation by rotation, updating these values at each step. We also keep track of the maximum profit seen so far and the number of rotations at which it occurred. The simulation continues as long as there are new customers arriving or there are customers still waiting to board.
Algorithm
- Initialize state variables:
waitingCustomers = 0,currentProfit = 0,maxProfit = 0,rotations = 0,resultRotations = -1, and an indexi = 0for thecustomersarray. - Use a single
whileloop that continues as long as there are new customers to process (i < customers.length) or there are customers waiting in line (waitingCustomers > 0). - In each iteration, which represents one rotation:
- Increment the
rotationscounter. - If
iis within the bounds of thecustomersarray, add the new customers (customers[i]) towaitingCustomersand incrementi. - Determine the number of customers to board:
boarded = min(waitingCustomers, 4). - Update
waitingCustomersby subtractingboarded. - Calculate the profit for this rotation and add it to
currentProfit:currentProfit += boarded * boardingCost - runningCost. - If
currentProfitis greater thanmaxProfit, updatemaxProfit = currentProfitandresultRotations = rotations.
- Increment the
- After the loop terminates, return
resultRotations. If profit never became positive,maxProfitwould remain0andresultRotationswould remain-1.
Walkthrough
We use a single while loop that continues as long as there are customers arriving (we haven't processed the whole customers array) or there are people waiting in line. Inside the loop, each iteration represents one rotation of the wheel.
- We increment the rotation count.
- If there are new customers scheduled to arrive for this rotation (i.e., we haven't exhausted the
customersarray), we add them to thewaitingCustomerscount. - We determine how many customers can board in this rotation, which is the minimum of the number of waiting customers and the capacity of a gondola (4).
- We update the number of
waitingCustomersby subtracting those who just boarded. - We calculate the profit for this rotation (
boarded * boardingCost - runningCost) and add it to ourcurrentProfit. - We then check if this
currentProfitis greater than themaxProfitfound so far. If it is, we updatemaxProfitand store the current number of rotations. - The loop terminates when all customers from the input array have arrived and the waiting line is empty.
- Finally, we return the number of rotations that yielded the maximum profit. If the maximum profit was never positive, we return -1.
We use long for profit variables to prevent potential integer overflow.
class Solution { public int minOperationsMaxProfit(int[] customers, int boardingCost, int runningCost) { long waitingCustomers = 0; long currentProfit = 0; long maxProfit = 0; // Start with 0, as we only care about positive profit int rotations = 0; int resultRotations = -1; int i = 0; while (i < customers.length || waitingCustomers > 0) { rotations++; if (i < customers.length) { waitingCustomers += customers[i]; i++; } long board = Math.min(waitingCustomers, 4); waitingCustomers -= board; currentProfit += board * boardingCost - runningCost; if (currentProfit > maxProfit) { maxProfit = currentProfit; resultRotations = rotations; } } return resultRotations; }}Complexity
Time
O(N + C/4), where N is the length of the `customers` array and C is the total number of customers. In the worst case, C can be up to N * 50. The total number of loop iterations is proportional to N plus the number of rotations needed to serve all customers.
Space
O(1), as we only use a few variables to keep track of the state.
Trade-offs
Pros
Simple to understand and implement.
Correctly models the problem statement step-by-step.
Cons
Can be less performant if the total number of customers is very large, as the simulation loop continues one rotation at a time even after all new customers have arrived.
This approach improves upon the simple simulation by first processing all customer arrivals in a loop. After this, instead of continuing to loop for any remaining customers, it calculates the profit from serving them in a more direct, mathematical way. This avoids a potentially long loop if there's a large queue of waiting customers.
Algorithm
- Initialize state variables:
waitingCustomers = 0,currentProfit = 0,maxProfit = 0,rotations = 0,resultRotations = -1. - Phase 1: Simulation during arrivals.
- Loop through the
customersarray. For each entrycustomers[i], simulate one rotation. - Increment
rotations, addcustomers[i]towaitingCustomers. - Board up to 4 customers, update
waitingCustomersandcurrentProfit. - Check if
currentProfitis a newmaxProfitand update if necessary.
- Loop through the
- Phase 2: Post-processing for remaining customers.
- After the loop, check if
waitingCustomers > 0. - Calculate the profit for a full rotation:
profitPerFour = 4 * boardingCost - runningCost. - If
profitPerFour <= 0, it's not profitable to continue, so we stop. - If
profitPerFour > 0:- Calculate the number of full rotations for the remaining customers:
fullRotations = waitingCustomers / 4. - Add the bulk profit
fullRotations * profitPerFourtocurrentProfitandfullRotationstorotations. - Check for a new
maxProfit. - Calculate the remaining customers after full rotations:
remaining = waitingCustomers % 4. - If
remaining > 0, simulate one final rotation for them, updatecurrentProfitandrotations, and perform a final check formaxProfit.
- Calculate the number of full rotations for the remaining customers:
- After the loop, check if
- Return
resultRotations.
Walkthrough
The simulation is split into two phases:
-
Initial Phase (during customer arrivals): We iterate through the
customersarray. In each iteration, we simulate one rotation, adding new customers, boarding up to 4, and updating the profit. We track the maximum profit throughout this phase. -
Post-processing Phase (after all arrivals): After the initial loop, we might have
waitingCustomersleft. Instead of looping, we calculate the profit from them analytically.- First, we determine if it's even profitable to continue. The best-case profit per rotation is
4 * boardingCost - runningCost. If this value is not positive, we stop. - If it is profitable, we calculate how many full rotations (boarding 4 customers) we can do with the
waitingCustomers. We compute the total profit and rotations from these in one step. - We then check if this new profit state gives us a new maximum.
- Finally, we handle the last few remaining customers (fewer than 4) with one final rotation and profit calculation, again checking if it results in a new maximum profit.
- First, we determine if it's even profitable to continue. The best-case profit per rotation is
This two-phase approach is more efficient as it replaces a potentially long loop with a few constant-time arithmetic operations.
class Solution { public int minOperationsMaxProfit(int[] customers, int boardingCost, int runningCost) { long waitingCustomers = 0; long currentProfit = 0; long maxProfit = 0; int rotations = 0; int resultRotations = -1; // Phase 1: Process customers as they arrive for (int customerCount : customers) { rotations++; waitingCustomers += customerCount; long board = Math.min(waitingCustomers, 4); waitingCustomers -= board; currentProfit += board * boardingCost - runningCost; if (currentProfit > maxProfit) { maxProfit = currentProfit; resultRotations = rotations; } } // Phase 2: Process remaining waiting customers if (waitingCustomers > 0) { long profitPerFour = (long)4 * boardingCost - runningCost; if (profitPerFour > 0) { long fullRotations = waitingCustomers / 4; currentProfit += fullRotations * profitPerFour; rotations += fullRotations; if (currentProfit > maxProfit) { maxProfit = currentProfit; resultRotations = rotations; } long remainingCustomers = waitingCustomers % 4; if (remainingCustomers > 0) { long lastProfit = remainingCustomers * boardingCost - runningCost; currentProfit += lastProfit; rotations++; if (currentProfit > maxProfit) { maxProfit = currentProfit; resultRotations = rotations; } } } } return resultRotations; }}Complexity
Time
O(N), where N is the length of the `customers` array. The initial simulation runs in O(N), and the post-processing step for any remaining customers takes constant O(1) time.
Space
O(1), using only a few variables for state tracking.
Trade-offs
Pros
More efficient in practice, especially when the total number of customers is much larger than the number of arrival days (N).
Replaces a potentially long loop with constant-time arithmetic operations for remaining customers.
Cons
The logic is slightly more complex due to the separation into two phases.
Solutions
Solution
class Solution {public int minOperationsMaxProfit(int[] customers, int boardingCost, int runningCost) { int ans = -1; int mx = 0, t = 0; int wait = 0, i = 0; while (wait > 0 || i < customers.length) { wait += i < customers.length ? customers[i] : 0; int up = Math.min(4, wait); wait -= up; ++i; t += up * boardingCost - runningCost; if (t > mx) { mx = t; ans = i; } } return ans; }}class Solution {public: int minOperationsMaxProfit(vector<int> &customers, int boardingCost, int runningCost) { int ans = -1; int mx = 0, t = 0; int wait = 0, i = 0; while (wait || i < customers.size()) { wait += i < customers.size() ? customers[i] : 0; int up = min(4, wait); wait -= up; ++i; t += up * boardingCost - runningCost; if (t > mx) { mx = t; ans = i; } } return ans; }};class Solution: def minOperationsMaxProfit(self, customers: List[int], boardingCost: int, runningCost: int) -> int: ans = - 1 mx = t = 0 wait = 0 i = 0 while wait or i < len(customers): wait += customers[i] if i < len(customers) else 0 up = wait if wait < 4 else 4 wait -= up t += up * boardingCost - runningCost i += 1 if t > mx: mx = t ans = i return ansVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.