Facebook Pixel

3155. Maximum Number of Upgradable Servers 🔒

Problem Description

You have n data centers, and each data center has servers that need to be upgraded. For each data center, you're given:

  • count[i]: The number of servers in data center i
  • upgrade[i]: The cost to upgrade one server in data center i
  • sell[i]: The money you receive from selling one server in data center i
  • money[i]: The initial money available for data center i

Your goal is to determine the maximum number of servers you can upgrade in each data center.

The key strategy is that you can sell some servers to get additional money, then use that money (plus your initial money) to upgrade the remaining servers. For example, if you have 10 servers and want to upgrade 6 of them, you could sell 4 servers to get extra funds, then use all your money to upgrade the remaining 6 servers.

Important constraints:

  • Money from one data center cannot be transferred to another data center - each data center's budget is independent
  • You can only upgrade servers that you haven't sold
  • The maximum number of servers you can upgrade is limited by both the total number of servers and your available budget

Return an array answer where answer[i] represents the maximum number of servers that can be upgraded in data center i.

The mathematical relationship is: if you want to upgrade x servers out of count[i] total servers, you can sell (count[i] - x) servers to get (count[i] - x) × sell[i] money. This money plus your initial money[i] must be enough to cover the upgrade cost of x × upgrade[i].

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

Intuition

Let's think about what happens when we want to upgrade x servers in a data center that has count[i] total servers.

If we upgrade x servers, we must sell (count[i] - x) servers to maximize our budget. The money we get from selling these servers is (count[i] - x) × sell[i]. Combined with our initial money money[i], our total budget becomes:

Total Budget = money[i] + (count[i] - x) × sell[i]

This budget must be enough to upgrade x servers, which costs x × upgrade[i]. So we need:

x × upgrade[i] ≤ money[i] + (count[i] - x) × sell[i]

Let's rearrange this inequality to solve for x:

  • x × upgrade[i] ≤ money[i] + count[i] × sell[i] - x × sell[i]
  • x × upgrade[i] + x × sell[i] ≤ money[i] + count[i] × sell[i]
  • x × (upgrade[i] + sell[i]) ≤ money[i] + count[i] × sell[i]
  • x ≤ (money[i] + count[i] × sell[i]) / (upgrade[i] + sell[i])

This gives us the maximum number of servers we can afford to upgrade based on our budget constraints.

However, there's another constraint: we can't upgrade more servers than we actually have. So x ≤ count[i].

Therefore, the maximum number of servers we can upgrade is: min(count[i], (money[i] + count[i] × sell[i]) / (upgrade[i] + sell[i]))

Since we need an integer result (we can't upgrade a fraction of a server), we use integer division: min(count[i], (money[i] + count[i] × sell[i]) // (upgrade[i] + sell[i]))

Learn more about Math and Binary Search patterns.

Solution Approach

The solution uses a straightforward mathematical approach to calculate the maximum upgradable servers for each data center independently.

For each data center i, we need to find the maximum value of x (number of servers to upgrade) such that:

  • We have enough money to upgrade x servers after selling (count[i] - x) servers
  • We don't exceed the total number of servers available

The mathematical formula derived from our intuition is: x ≤ (count[i] × sell[i] + money[i]) / (upgrade[i] + sell[i])

The implementation iterates through all data centers using Python's zip function to process the corresponding elements from all four input arrays simultaneously:

for cnt, cost, income, cash in zip(count, upgrade, sell, money):

For each data center, we calculate:

  1. The budget-constrained maximum: (cnt * income + cash) // (cost + income)

    • cnt * income represents the money we'd get if we sold all servers
    • Adding cash gives us the total available money
    • Dividing by (cost + income) gives us the maximum servers we can upgrade
    • Integer division // ensures we get a whole number
  2. The physical constraint: cnt (we can't upgrade more servers than we have)

  3. Take the minimum of these two values: min(cnt, (cnt * income + cash) // (cost + income))

The result for each data center is appended to the answer array, which is returned at the end.

This approach has a time complexity of O(n) where n is the number of data centers, and space complexity of O(n) for storing the answer array.

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 a concrete example with 2 data centers:

  • count = [4, 3] (servers in each data center)
  • upgrade = [3, 5] (cost to upgrade one server)
  • sell = [4, 2] (money from selling one server)
  • money = [8, 9] (initial budget)

Data Center 0 (index 0):

  • We have 4 servers total
  • Let's determine how many servers we can upgrade

Using our formula: min(count[0], (money[0] + count[0] × sell[0]) // (upgrade[0] + sell[0]))

Calculate the budget-based maximum:

  • Total potential money = money[0] + count[0] × sell[0] = 8 + 4 × 4 = 8 + 16 = 24
  • Cost per server (upgrade + opportunity cost of not selling) = upgrade[0] + sell[0] = 3 + 4 = 7
  • Maximum affordable upgrades = 24 // 7 = 3

Physical constraint: count[0] = 4

Result: min(4, 3) = 3 servers can be upgraded

Let's verify: If we upgrade 3 servers, we sell 1 server:

  • Money from selling: 1 × 4 = 4
  • Total budget: 8 + 4 = 12
  • Cost to upgrade 3 servers: 3 × 3 = 9
  • Since 12 ≥ 9, we can indeed upgrade 3 servers ✓

Data Center 1 (index 1):

  • We have 3 servers total

Calculate the budget-based maximum:

  • Total potential money = money[1] + count[1] × sell[1] = 9 + 3 × 2 = 9 + 6 = 15
  • Cost per server = upgrade[1] + sell[1] = 5 + 2 = 7
  • Maximum affordable upgrades = 15 // 7 = 2

Physical constraint: count[1] = 3

Result: min(3, 2) = 2 servers can be upgraded

Let's verify: If we upgrade 2 servers, we sell 1 server:

  • Money from selling: 1 × 2 = 2
  • Total budget: 9 + 2 = 11
  • Cost to upgrade 2 servers: 2 × 5 = 10
  • Since 11 ≥ 10, we can upgrade 2 servers ✓

Final Answer: [3, 2]

Solution Implementation

1from typing import List
2
3
4class Solution:
5    def maxUpgrades(
6        self, count: List[int], upgrade: List[int], sell: List[int], money: List[int]
7    ) -> List[int]:
8        """
9        Calculate the maximum number of items that can be upgraded for each test case.
10      
11        Args:
12            count: List of initial item counts
13            upgrade: List of upgrade costs per item
14            sell: List of selling prices per item
15            money: List of initial money amounts
16          
17        Returns:
18            List of maximum upgradeable items for each test case
19        """
20        result = []
21      
22        # Process each test case
23        for item_count, upgrade_cost, sell_price, initial_money in zip(count, upgrade, sell, money):
24            # Calculate maximum upgradeable items
25            # Formula: min(total_items, (total_money_from_selling + initial_money) / total_cost_per_upgrade)
26            # Where total_cost_per_upgrade = upgrade_cost + sell_price (opportunity cost)
27            max_upgradeable = min(
28                item_count, 
29                (item_count * sell_price + initial_money) // (upgrade_cost + sell_price)
30            )
31            result.append(max_upgradeable)
32          
33        return result
34
1class Solution {
2    /**
3     * Calculates the maximum number of upgrades possible for each item.
4     * 
5     * @param count   Array representing the initial count of each item
6     * @param upgrade Array representing the upgrade cost for each item
7     * @param sell    Array representing the sell price for each item
8     * @param money   Array representing the available money for each item
9     * @return Array containing the maximum upgrades possible for each item
10     */
11    public int[] maxUpgrades(int[] count, int[] upgrade, int[] sell, int[] money) {
12        int n = count.length;
13        int[] result = new int[n];
14      
15        // Process each item independently
16        for (int i = 0; i < n; i++) {
17            // Calculate maximum upgrades based on two constraints:
18            // 1. Cannot upgrade more than the current count
19            // 2. Total cost of upgrades cannot exceed available funds
20          
21            // Formula derivation:
22            // Let x be the number of items to upgrade
23            // Money from selling (count - x) items: (count - x) * sell
24            // Total available money: (count - x) * sell + money
25            // Cost to upgrade x items: x * upgrade
26            // Constraint: x * upgrade <= (count - x) * sell + money
27            // Solving for x: x <= (count * sell + money) / (upgrade + sell)
28          
29            long totalFunds = (long) count[i] * sell[i] + money[i];
30            int totalCostPerUpgrade = upgrade[i] + sell[i];
31            int maxAffordableUpgrades = (int) (totalFunds / totalCostPerUpgrade);
32          
33            // Take minimum of count limit and affordable upgrades
34            result[i] = Math.min(count[i], maxAffordableUpgrades);
35        }
36      
37        return result;
38    }
39}
40
1class Solution {
2public:
3    vector<int> maxUpgrades(vector<int>& count, vector<int>& upgrade, vector<int>& sell, vector<int>& money) {
4        int n = count.size();
5        vector<int> result;
6      
7        // Process each item type independently
8        for (int i = 0; i < n; ++i) {
9            // Calculate maximum possible upgrades for item i
10            // Strategy: We can sell some items to fund upgrades for the remaining items
11            // Total money available = initial money + money from selling items
12            // Let x be the number of items to upgrade
13            // We need: x * upgrade[i] <= money[i] + (count[i] - x) * sell[i]
14            // Solving for x: x <= (count[i] * sell[i] + money[i]) / (upgrade[i] + sell[i])
15          
16            // Use long long to prevent integer overflow during multiplication
17            long long totalFunds = static_cast<long long>(count[i]) * sell[i] + money[i];
18            int totalCost = upgrade[i] + sell[i];
19            int maxPossibleUpgrades = static_cast<int>(totalFunds / totalCost);
20          
21            // Cannot upgrade more items than we have
22            int actualUpgrades = min(count[i], maxPossibleUpgrades);
23            result.push_back(actualUpgrades);
24        }
25      
26        return result;
27    }
28};
29
1/**
2 * Calculates the maximum number of upgrades possible for each item
3 * @param count - Array of current item counts
4 * @param upgrade - Array of upgrade costs for each item
5 * @param sell - Array of selling prices for each item
6 * @param money - Array of available money for each item
7 * @returns Array of maximum possible upgrades for each item
8 */
9function maxUpgrades(
10    count: number[],
11    upgrade: number[],
12    sell: number[],
13    money: number[],
14): number[] {
15    // Get the length of input arrays
16    const arrayLength: number = count.length;
17  
18    // Initialize result array to store maximum upgrades for each item
19    const result: number[] = [];
20  
21    // Iterate through each item
22    for (let index = 0; index < arrayLength; ++index) {
23        // Calculate maximum upgrades possible
24        // Formula: (current items * sell price + available money) / (upgrade cost + sell price)
25        // Use bitwise OR with 0 to truncate to integer (equivalent to Math.floor for positive numbers)
26        const maxPossibleUpgrades: number = 
27            ((count[index] * sell[index] + money[index]) / (upgrade[index] + sell[index])) | 0;
28      
29        // The actual maximum upgrades cannot exceed the current count
30        // Take the minimum between calculated upgrades and current count
31        result.push(Math.min(maxPossibleUpgrades, count[index]));
32    }
33  
34    return result;
35}
36

Time and Space Complexity

The time complexity is O(n), where n is the length of the input arrays. The algorithm iterates through all four arrays simultaneously using zip(), performing a constant number of operations for each element (one arithmetic calculation with addition, multiplication, and integer division, followed by a min() operation between two values). Since we process each element exactly once with constant-time operations, the overall time complexity is linear.

The space complexity is O(1) if we exclude the space used for the output array ans. The algorithm only uses a fixed amount of extra space for the loop variables (cnt, cost, income, cash) regardless of the input size. Including the output array, the space complexity would be O(n) since we store one result for each input element.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Division by Zero Error

The Pitfall: If both upgrade[i] and sell[i] are 0 for any data center, the formula (cnt * income + cash) // (cost + income) will cause a division by zero error.

Why it happens: While it might seem unlikely in a real scenario, edge cases where both upgrading and selling have zero cost/price could exist in test data.

Solution: Add a check before performing the division:

for item_count, upgrade_cost, sell_price, initial_money in zip(count, upgrade, sell, money):
    # Handle edge case where both costs are zero
    if upgrade_cost + sell_price == 0:
        # If upgrade cost is 0, we can upgrade all servers
        max_upgradeable = item_count
    else:
        max_upgradeable = min(
            item_count, 
            (item_count * sell_price + initial_money) // (upgrade_cost + sell_price)
        )
    result.append(max_upgradeable)

2. Integer Overflow in Large Calculations

The Pitfall: The calculation item_count * sell_price + initial_money could potentially overflow if the values are extremely large.

Why it happens: When multiplying large numbers (e.g., millions of servers with high sell prices), the intermediate result might exceed typical integer limits in some programming languages.

Solution: While Python handles arbitrary precision integers automatically, in other languages or for optimization, you might need to rearrange the formula to avoid overflow:

# Alternative calculation to minimize overflow risk
# Instead of: (cnt * sell + money) // (upgrade + sell)
# Use: cnt - max(0, (cnt * upgrade - money) // (upgrade + sell))
servers_to_sell = max(0, (item_count * upgrade_cost - initial_money + upgrade_cost + sell_price - 1) // (upgrade_cost + sell_price))
max_upgradeable = item_count - servers_to_sell

3. Incorrect Handling of Zero or Negative Values

The Pitfall: Not properly handling cases where money[i] could be 0 or where sell[i] might be greater than upgrade[i].

Why it happens: The formula assumes standard economic behavior, but edge cases might include scenarios where selling servers gives more money than upgrading costs.

Solution: Ensure proper handling of all value ranges:

for item_count, upgrade_cost, sell_price, initial_money in zip(count, upgrade, sell, money):
    # Handle negative or zero counts
    if item_count <= 0:
        result.append(0)
        continue
  
    # Handle case where selling is more profitable than upgrade cost
    if sell_price > upgrade_cost and initial_money >= 0:
        # Can potentially upgrade all servers if selling generates profit
        max_upgradeable = item_count
    elif upgrade_cost + sell_price > 0:
        max_upgradeable = min(
            item_count, 
            max(0, (item_count * sell_price + initial_money) // (upgrade_cost + sell_price))
        )
    else:
        max_upgradeable = item_count if upgrade_cost == 0 else 0
  
    result.append(max_upgradeable)
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What's the relationship between a tree and a graph?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More