You have an inventory
of different colored balls, and there is a customer that wants orders
balls of any color.
The customer weirdly values the colored balls. Each colored ball's value is the number of balls of that color you currently have in your inventory
. For example, if you own 6
yellow balls, the customer would pay 6
for the first yellow ball. After the transaction, there are only 5
yellow balls left, so the next yellow ball is then valued at 5
(i.e., the value of the balls decreases as you sell more to the customer).
You are given an integer array, inventory
, where inventory[i]
represents the number of balls of the ith
color that you initially own. You are also given an integer orders
, which represents the total number of balls that the customer wants. You can sell the balls in any order.
Return the maximum total value that you can attain after selling orders
colored balls. As the answer may be too large, return it modulo 109 + 7
.
Example 1:
Input: inventory = [2,5], orders = 4 Output: 14 Explanation: Sell the 1st color 1 time (2) and the 2nd color 3 times (5 + 4 + 3). The maximum total value is 2 + 5 + 4 + 3 = 14.
Example 2:
Input: inventory = [3,5], orders = 6 Output: 19 Explanation: Sell the 1st color 2 times (3 + 2) and the 2nd color 4 times (5 + 4 + 3 + 2). The maximum total value is 3 + 2 + 5 + 4 + 3 + 2 = 19.
Constraints:
1 <= inventory.length <= 105
1 <= inventory[i] <= 109
1 <= orders <= min(sum(inventory[i]), 109)
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to selling diminishing-valued balls involves exploring every possible combination of ball sales. We aim to find the combination that yields the highest total value by meticulously considering each sale option. This involves trying every possible quantity for each color, one sale at a time.
Here's how the algorithm would work step-by-step:
def sell_diminishing_valued_colored_balls_brute_force(inventory, orders):
total_profit = 0
# Iterate up to the number of orders
for _ in range(orders):
max_profit_increase = 0
color_to_sell = -1
# Find the color with the highest profit
for color_index in range(len(inventory)):
current_profit = inventory[color_index]
if current_profit > max_profit_increase:
max_profit_increase = current_profit
color_to_sell = color_index
# Ensure a color can be sold.
if color_to_sell != -1:
total_profit += inventory[color_to_sell]
# Reduce inventory of chosen color
inventory[color_to_sell] -= 1
return total_profit
The key to maximizing profit is to sell the most valuable balls first. We use a strategy to quickly figure out how many balls of different values we should sell to meet the sales goal, taking into account the diminishing value as we sell more of each color.
Here's how the algorithm would work step-by-step:
def max_profit(inventory, orders):
left_value = 1
right_value = max(inventory)
maximum_profit = 0
modulo_value = 10**9 + 7
while left_value <= right_value:
mid_value = (left_value + right_value) // 2
number_of_balls_we_can_sell = 0
for ball_value in inventory:
if ball_value >= mid_value:
number_of_balls_we_can_sell += ball_value - mid_value + 1
# Narrow the search to find the optimal minimum ball value.
if number_of_balls_we_can_sell >= orders:
left_value = mid_value + 1
else:
right_value = mid_value - 1
minimum_value = right_value
for ball_value in inventory:
if ball_value > minimum_value:
maximum_profit += (ball_value * (ball_value + 1)) // 2 - (minimum_value * (minimum_value + 1)) // 2
maximum_profit %= modulo_value
orders -= ball_value - minimum_value
# Calculate profit from selling remaining balls at the minimum value.
maximum_profit += minimum_value * orders
maximum_profit %= modulo_value
return maximum_profit
Case | How to Handle |
---|---|
inventory is null or empty | Return 0, as no balls can be sold. |
orders is 0 | Return 0, as no balls need to be sold. |
inventory contains only one color | Handle by calculating the sum of an arithmetic series from inventory[0] down to inventory[0] - orders + 1 (or 1, whichever is greater). |
inventory contains very large numbers and orders is also very large, potentially leading to integer overflow during calculation | Use long data type for intermediate calculations and the final result to prevent integer overflow. |
orders is larger than the total number of balls in the inventory | Calculate the revenue by selling all the balls until each color has 0 balls. |
All colors in inventory have the same number of balls | Calculate revenue by selling balls equally from each color until orders is met. |
inventory contains extreme boundary values (e.g., Integer.MAX_VALUE) | Ensure calculations avoid exceeding the maximum integer value, possibly by using long data types and careful ordering of operations. |
Inventory is very large, impacting memory usage and potentially causing performance issues | Binary search approach ensures performance is logarithmic relative to ball counts, and space complexity is constant/linear depending on whether in-place sorting is used. |