礼盒的甜蜜度是 k 种不同的糖果中,任意两种糖果价格差的绝对值的最小值。计算礼盒的甜蜜度时,可以先将 k 种糖果按照价格排序,然后计算相邻的价格差的绝对值,然后取出最小值。
要求甜蜜度的最大值,可以采用二分查找的方法。先假设一个甜蜜度 mid,然后尝试在排好序的 price 中找出 k 种糖果,并且任意两种相邻的价格差绝对值都大于 mid。如果可以找到这样的 k 种糖果,则说明可能存在更大的甜蜜度,需要修改二分查找的下边界;如果找不到这样的 k 种糖果,则说明最大的甜蜜度只可能更小,需要修改二分查找的上边界。
在假设一个甜蜜度 mid 后,在排好序的 price 中找 k 种糖果时,需要用到贪心的算法。即从小到大遍历 price 的元素,如果当前糖果的价格比上一个选中的糖果的价格的差大于 mid,则选中当前糖果,否则继续考察下一个糖果。
classSolution: defmaximumTastiness(self, price: List[int], k: int) -> int: price.sort() left, right = 0, price[-1] - price[0] while left < right: mid = (left + right + 1) // 2 if self.check(price, k, mid): left = mid else: right = mid - 1 return left
defcheck(self, price: List[int], k: int, tastiness: int) -> bool: prev = -inf cnt = 0 for p in price: if p - prev >= tastiness: cnt += 1 prev = p return cnt >= k
classSolution { public: intmaximumTastiness(vector<int>& price, int k){ int n = price.size(); sort(price.begin(), price.end()); int left = 0, right = price[n - 1] - price[0]; while (left < right) { int mid = (left + right + 1) >> 1; if (check(price, k, mid)) { left = mid; } else { right = mid - 1; } } return left; }
boolcheck(const vector<int> &price, int k, int tastiness){ int prev = INT_MIN >> 1; int cnt = 0; for (int p : price) { if (p - prev >= tastiness) { cnt++; prev = p; } } return cnt >= k; } };
boolcheck(constint* price, int priceSize,int k, int tastiness) { int prev = INT_MIN >> 1; int cnt = 0; for (int i = 0; i < priceSize; i++) { int p = price[i]; if (p - prev >= tastiness) { cnt++; prev = p; } } return cnt >= k; }
funcmaximumTastiness(price []int, k int)int { sort.Ints(price) left, right := 0, price[len(price)-1]-price[0] for left < right { mid := (left + right + 1) / 2 if check(price, k, mid) { left = mid } else { right = mid - 1 } } return left }
funccheck(price []int, k int, tastiness int)bool { prev := int(math.Inf(-1)) >> 1 cnt := 0 for _, p := range price { if p - prev >= tastiness { cnt++ prev = p } } return cnt >= k }
复杂度分析
时间复杂度:O(n \log n + n \log C),其中 n 是数组 price 的长度,C 是数组 price 的最大值与最小值之差。排序的时间是 O(n \log n),二分查找的次数是 O(\log C),每次查找的时间是 O(n)。