Maximum Tastiness of Candy Basket

medium binary search greedy sorting

Problem

Given an array price where price[i] is the cost of the i-th candy and an integer k, choose exactly k candies. The tastiness of a basket is the smallest absolute difference between any two chosen prices. Return the largest tastiness you can achieve.

Inputprice = [13, 5, 1, 8, 21, 2], k = 3
Output8
Sort → [1,2,5,8,13,21]; choosing 5, 13, 21 gives gaps 8 and 8, so the minimum gap (tastiness) is 8 — the best possible.

def maximum_tastiness(price, k):
    price.sort()
    def can(gap):
        count, last = 1, price[0]
        for x in price[1:]:
            if x - last >= gap:
                count += 1
                last = x
        return count >= k
    lo, hi = 0, price[-1] - price[0]
    while lo < hi:
        mid = (lo + hi + 1) // 2
        if can(mid): lo = mid
        else: hi = mid - 1
    return lo
function maximumTastiness(price, k) {
  price.sort((a, b) => a - b);
  const can = (gap) => {
    let count = 1, last = price[0];
    for (let i = 1; i < price.length; i++) {
      if (price[i] - last >= gap) { count++; last = price[i]; }
    }
    return count >= k;
  };
  let lo = 0, hi = price[price.length - 1] - price[0];
  while (lo < hi) {
    const mid = (lo + hi + 1) >> 1;
    if (can(mid)) lo = mid; else hi = mid - 1;
  }
  return lo;
}
class Solution {
    public int maximumTastiness(int[] price, int k) {
        java.util.Arrays.sort(price);
        int lo = 0, hi = price[price.length - 1] - price[0];
        while (lo < hi) {
            int mid = lo + (hi - lo + 1) / 2;
            if (canPick(price, mid, k)) lo = mid;
            else hi = mid - 1;
        }
        return lo;
    }
    private boolean canPick(int[] price, int gap, int k) {
        int count = 1, last = price[0];
        for (int i = 1; i < price.length; i++) {
            if (price[i] - last >= gap) { count++; last = price[i]; }
        }
        return count >= k;
    }
}
int maximumTastiness(vector<int>& price, int k) {
    sort(price.begin(), price.end());
    auto can = [&](int gap) {
        int count = 1, last = price[0];
        for (int i = 1; i < (int)price.size(); i++) {
            if (price[i] - last >= gap) { count++; last = price[i]; }
        }
        return count >= k;
    };
    int lo = 0, hi = price.back() - price.front();
    while (lo < hi) {
        int mid = lo + (hi - lo + 1) / 2;
        if (can(mid)) lo = mid;
        else hi = mid - 1;
    }
    return lo;
}
Time: O(n log n + n log V) Space: O(1)