[LeetCode] 2517. Maximum Tastiness of Candy Basket
You are given an array of positive integers price
where price[i]
denotes the price of the ith
candy and a positive integer k
.
The store sells baskets of k
distinct candies. The tastiness of a candy basket is the smallest absolute difference of the prices of any two candies in the basket.
Return the maximum tastiness of a candy basket.
Example 1:
Input: price = [13,5,1,8,21,2], k = 3 Output: 8 Explanation: Choose the candies with the prices [13,5,21]. The tastiness of the candy basket is: min(|13 - 5|, |13 - 21|, |5 - 21|) = min(8, 8, 16) = 8. It can be proven that 8 is the maximum tastiness that can be achieved.
Example 2:
Input: price = [1,3,1], k = 2 Output: 2 Explanation: Choose the candies with the prices [1,3]. The tastiness of the candy basket is: min(|1 - 3|) = min(2) = 2. It can be proven that 2 is the maximum tastiness that can be achieved.
Example 3:
Input: price = [7,7,7,7], k = 2 Output: 0 Explanation: Choosing any two distinct candies from the candies we have will result in a tastiness of 0.
Constraints:
2 <= k <= price.length <= 105
1 <= price[i] <= 109
礼盒的最大甜蜜度。
给你一个正整数数组 price ,其中 price[i] 表示第 i 类糖果的价格,另给你一个正整数 k 。
商店组合 k 类 不同 糖果打包成礼盒出售。礼盒的 甜蜜度 是礼盒中任意两种糖果 价格 绝对差的最小值。
返回礼盒的 最大 甜蜜度。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/maximum-tastiness-of-candy-basket
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路是排序 + 二分,而且这道题是在答案上做二分。
首先我们思考一下暴力解。为了得到一个合适的甜蜜度,同时尽快地找到每两个礼盒之间价格的差值,我们势必要对 input 数组排序,这样我们才能尽快找到甜蜜度相邻的礼盒之间的差值。排序之后,因为需要找 k 个礼盒,那么我们需要一个两层循环,第一层遍历每 k 个礼盒的第一个,第二层我们需要去看 k 个礼盒,并计算他们两两间价格绝对差的最小值。如果 k 非常大,暴力解的时间复杂度会到 O(nk),几乎就是一个两层 for 循环的速度。
优化的办法是排序 + 二分。这里排序还是必不可少,因为需要以最快的速度找到礼盒间的价格差。这里我们对答案进行二分,意思是我们去猜测一个绝对差,看看这个差值是否能让我们找到 k 个礼盒。为了简单起见,二分的下界我取 0,上界我取 Integer.MAX_VALUE。这道题二分的代码稍微有一些特殊,我写的时候选择了左闭右开的方式(left < right)。当我们找到一个 mid 值的时候,我们去尝试看看 helper 函数是否能返回 true,如果返回,说明这个猜测的 mid 值一定能满足题意,left = mid + 1。当我们跳出 while 循环的时候,因为在跳出前 left = mid + 1,mid 是跳出之前能找到的最小的合法值,所以最后返回的是 left - 1,其实就是 mid。
时间O(n^2)
空间O(1)
Java实现
1 class Solution { 2 public int maximumTastiness(int[] price, int k) { 3 Arrays.sort(price); 4 int n = price.length; 5 int left = 0; 6 int right = Integer.MAX_VALUE; 7 while (left < right) { 8 int mid = left + (right - left) / 2; 9 if (helper(mid, price, k)) { 10 left = mid + 1; 11 } else { 12 right = mid; 13 } 14 } 15 return left - 1; 16 } 17 18 private boolean helper(int target, int[] price, int k) { 19 int prev = price[0]; 20 int count = 1; 21 for (int i = 1; i < price.length; i++) { 22 if (price[i] - prev >= target) { 23 count++; 24 prev = price[i]; 25 } 26 if (count == k) { 27 return true; 28 } 29 } 30 return false; 31 } 32 }