2706. Buy Two Chocolates - Explanation

Problem Link

Description

You are given an integer array prices representing the prices of various chocolates in a store. You are also given a single integer money, which represents your initial amount of money.

You must buy exactly two chocolates in such a way that you still have some non-negative leftover money. You would like to minimize the sum of the prices of the two chocolates you buy.

Return the amount of money you will have leftover after buying the two chocolates. If there is no way for you to buy two chocolates without ending up in debt, return money. Note that the leftover must be non-negative.

Example 1:

Input: prices = [1,3,2], money = 5

Output: 2

Explanation: Buy the two chocolates with prices 1 + 2. The leftover money is 5 - 3 = 2.

Example 2:

Input: prices = [2,5,1,2], money = 3

Output: 0

Explanation: Buy the two chocolates with prices 1 + 2. The leftover money is 3 - 3 = 0.

Example 3:

Input: prices = [2,2,4,3], money = 2

Output: 2

Explanation: There is no way to buy two chocolates. So, we return the given money 2.

Constraints:

  • 2 <= prices.length <= 50
  • 1 <= prices[i], money <= 100


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • Arrays - Basic array traversal and accessing elements by index
  • Sorting - Understanding how sorting works and its time complexity
  • Greedy Algorithms - Making locally optimal choices to find a global optimum

1. Brute Force

Intuition

We want to buy two chocolates and maximize the leftover money, which means we should minimize the total cost of the two chocolates. The brute force approach tries every possible pair of chocolates and keeps track of the maximum leftover (or equivalently, the pair with minimum total cost that we can afford).

Algorithm

  1. Initialize result to -1 (indicating no valid purchase found yet).
  2. For each pair of chocolates (i, j) where i < j:
    • If the sum of their prices is within our budget, calculate the leftover money.
    • Update result with the maximum leftover found.
  3. If no valid pair was found (result is -1), return the original money (we buy nothing).
  4. Otherwise, return the maximum leftover amount.
class Solution:
    def buyChoco(self, prices: List[int], money: int) -> int:
        res = -1
        for i in range(len(prices)):
            for j in range(i + 1, len(prices)):
                if prices[i] + prices[j] <= money:
                    res = max(res, money - prices[i] - prices[j])
        return res if res != -1 else money

Time & Space Complexity

  • Time complexity: O(n2)O(n ^ 2)
  • Space complexity: O(1)O(1) extra space.

2. Sorting

Intuition

To maximize leftover money, we need to buy the two cheapest chocolates. After sorting the prices, the two cheapest chocolates will be at the beginning of the array. We just need to check if we can afford them.

Algorithm

  1. Sort the prices array in ascending order.
  2. Calculate the cost of buying the two cheapest chocolates (first two elements).
  3. If this cost exceeds our money, return the original money (we buy nothing).
  4. Otherwise, return money minus the cost of the two chocolates.
class Solution:
    def buyChoco(self, prices: List[int], money: int) -> int:
        prices.sort()
        buy = prices[0] + prices[1]
        return money if buy > money else money - buy

Time & Space Complexity

  • Time complexity: O(nlogn)O(n \log n)
  • Space complexity: O(1)O(1) or O(n)O(n) depending on the sorting algorithm.

3. Greedy

Intuition

We can find the two cheapest chocolates in a single pass without sorting. As we iterate through the prices, we maintain the two smallest values seen so far. This gives us the optimal pair to buy.

Algorithm

  1. Initialize two variables to track the smallest (min1) and second smallest (min2) prices, both set to infinity.
  2. Iterate through each price:
    • If the current price is less than min1, update min2 to be the old min1, and min1 to be the current price.
    • Otherwise, if the current price is less than min2, update min2 to be the current price.
  3. Calculate the leftover money after buying chocolates at min1 and min2 prices.
  4. If leftover is non-negative, return it; otherwise, return the original money.
class Solution:
    def buyChoco(self, prices: list[int], money: int) -> int:
        min1 = min2 = float('inf')

        for p in prices:
            if p < min1:
                min1, min2 = p, min1
            elif p < min2:
                min2 = p

        leftover = money - min1 - min2
        return leftover if leftover >= 0 else money

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(1)O(1) extra space.

Common Pitfalls

Returning Leftover When You Cannot Afford Both Chocolates

If the sum of the two cheapest chocolates exceeds your money, you should return the original money (buy nothing), not a negative leftover or zero.

# Wrong: returning negative leftover
return money - min1 - min2  # Could be negative
# Correct: check if affordable first

Not Updating Both Minimums Correctly

When finding a new smallest price, forgetting to shift the old minimum to become the second minimum loses track of valid candidates.

# Wrong: losing second minimum
if p < min1:
    min1 = p  # min2 is never updated with old min1