Minimum Cost of Buying Candies With Discount

easy array greedy sorting

Problem

For every two candies you buy, the shop gives a third candy free, as long as the free candy costs no more than the cheaper of the two you bought. Given an array cost of candy prices, return the minimum total cost to buy all candies.

Greedy insight: sort prices high to low and process them in triples. In each triple you pay for the two most expensive candies and take the third (the cheapest of the trio) for free, so the free candies are the ones at sorted positions 2, 5, 8, …

Inputcost = [6,5,7,9,2,2]
Output23
Sorted: [9,7,6,5,2,2]. Buy 9 & 7, free 6; buy 5 & 2, free 2. Total = 9+7+5+2 = 23.

def minimumCost(cost):
    cost.sort(reverse=True)         # most expensive first
    total = 0
    for i in range(len(cost)):
        if i % 3 == 2:              # every third candy is free
            continue
        total += cost[i]           # pay for this candy
    return total
function minimumCost(cost) {
  cost.sort((a, b) => b - a);      // most expensive first
  let total = 0;
  for (let i = 0; i < cost.length; i++) {
    if (i % 3 === 2) continue;     // every third candy is free
    total += cost[i];              // pay for this candy
  }
  return total;
}
int minimumCost(int[] cost) {
    Integer[] c = new Integer[cost.length];
    for (int i = 0; i < cost.length; i++) c[i] = cost[i];
    Arrays.sort(c, Collections.reverseOrder());  // high to low
    int total = 0;
    for (int i = 0; i < c.length; i++) {
        if (i % 3 == 2) continue;   // every third candy is free
        total += c[i];              // pay for this candy
    }
    return total;
}
int minimumCost(vector<int>& cost) {
    sort(cost.rbegin(), cost.rend());  // most expensive first
    int total = 0;
    for (int i = 0; i < (int)cost.size(); i++) {
        if (i % 3 == 2) continue;      // every third candy is free
        total += cost[i];              // pay for this candy
    }
    return total;
}
Time: O(n log n) Space: O(1) beyond the sort