Skip to content

Files

Latest commit

a7f9b88 · Jun 11, 2023

History

History
246 lines (200 loc) · 6.84 KB

File metadata and controls

246 lines (200 loc) · 6.84 KB

English Version

题目描述

给你一个正整数数组 price ,其中 price[i] 表示第 i 类糖果的价格,另给你一个正整数 k

商店组合 k不同 糖果打包成礼盒出售。礼盒的 甜蜜度 是礼盒中任意两种糖果 价格 绝对差的最小值。

返回礼盒的 最大 甜蜜度

 

示例 1:

输入:price = [13,5,1,8,21,2], k = 3
输出:8
解释:选出价格分别为 [13,5,21] 的三类糖果。
礼盒的甜蜜度为 min(|13 - 5|, |13 - 21|, |5 - 21|) = min(8, 8, 16) = 8 。
可以证明能够取得的最大甜蜜度就是 8 。

示例 2:

输入:price = [1,3,1], k = 2
输出:2
解释:选出价格分别为 [1,3] 的两类糖果。 
礼盒的甜蜜度为 min(|1 - 3|) = min(2) = 2 。
可以证明能够取得的最大甜蜜度就是 2 。

示例 3:

输入:price = [7,7,7,7], k = 2
输出:0
解释:从现有的糖果中任选两类糖果,甜蜜度都会是 0 。

 

提示:

  • 2 <= k <= price.length <= 105
  • 1 <= price[i] <= 109

解法

方法一:贪心 + 二分查找

我们注意到,如果一个甜蜜度为 x 的礼盒是可行的,那么甜蜜度小于 x 的礼盒也是可行的,这存在着单调性,因此我们可以使用二分查找的方法,找到最大的可行甜蜜度。

我们首先将数组 p r i c e 排序,然后定义二分查找的左边界 l = 0 , r = p r i c e [ n 1 ] p r i c e [ 0 ] 。每一次,我们计算出当前的中间值 m i d = l + r + 1 2 ,以 m i d 作为甜蜜度,判断是否可行。若可行,那么我们将左边界 l 更新为 m i d ,否则将右边界 r 更新为 m i d 1 。最后返回 l 即可。

那么问题的关键转化为:判断一个甜蜜度是否可行,我们通过函数 c h e c k ( x ) 来实现。函数 c h e c k ( x ) 的执行逻辑如下:

定义一个变量 c n t 表示当前已经选取的糖果的数量,初始值为 0 ,定义一个变量 p r e 表示上一个选取的糖果的价格,初始值为 x 。然后我们遍历排好序的数组 p r i c e ,对于每一个糖果的价格 c u r ,如果 c u r p r e x ,那么我们就选取这个糖果,将 p r e 更新为 c u r ,并将 c n t 加一。最后判断 c n t 是否大于等于 k ,如果是,那么返回 t r u e ,否则返回 f a l s e

时间复杂度 O ( n × ( log n + log M ) ) ,空间复杂度 O ( log n ) 。其中 n 是数组 p r i c e 的长度;而 M 是数组 p r i c e 中的最大值,本题中 M 10 9

Python3

class Solution:
    def maximumTastiness(self, price: List[int], k: int) -> int:
        def check(x: int) -> bool:
            cnt, pre = 0, -x
            for cur in price:
                if cur - pre >= x:
                    pre = cur
                    cnt += 1
            return cnt >= k

        price.sort()
        l, r = 0, price[-1] - price[0]
        while l < r:
            mid = (l + r + 1) >> 1
            if check(mid):
                l = mid
            else:
                r = mid - 1
        return l

Java

class Solution {
    public int maximumTastiness(int[] price, int k) {
        Arrays.sort(price);
        int l = 0, r = price[price.length - 1] - price[0];
        while (l < r) {
            int mid = (l + r + 1) >> 1;
            if (check(price, k, mid)) {
                l = mid;
            } else {
                r = mid - 1;
            }
        }
        return l;
    }

    private boolean check(int[] price, int k, int x) {
        int cnt = 0, pre = -x;
        for (int cur : price) {
            if (cur - pre >= x) {
                pre = cur;
                ++cnt;
            }
        }
        return cnt >= k;
    }
}

C++

class Solution {
public:
    int maximumTastiness(vector<int>& price, int k) {
        sort(price.begin(), price.end());
        int l = 0, r = price.back() - price[0];
        auto check = [&](int x) -> bool {
            int cnt = 0, pre = -x;
            for (int& cur : price) {
                if (cur - pre >= x) {
                    pre = cur;
                    ++cnt;
                }
            }
            return cnt >= k;
        };
        while (l < r) {
            int mid = (l + r + 1) >> 1;
            if (check(mid)) {
                l = mid;
            } else {
                r = mid - 1;
            }
        }
        return l;
    }
};

Go

func maximumTastiness(price []int, k int) int {
	sort.Ints(price)
	return sort.Search(price[len(price)-1], func(x int) bool {
		cnt, pre := 0, -x
		for _, cur := range price {
			if cur-pre >= x {
				pre = cur
				cnt++
			}
		}
		return cnt < k
	}) - 1
}

TypeScript

function maximumTastiness(price: number[], k: number): number {
    price.sort((a, b) => a - b);
    let l = 0;
    let r = price[price.length - 1] - price[0];
    const check = (x: number): boolean => {
        let [cnt, pre] = [0, -x];
        for (const cur of price) {
            if (cur - pre >= x) {
                pre = cur;
                ++cnt;
            }
        }
        return cnt >= k;
    };
    while (l < r) {
        const mid = (l + r + 1) >> 1;
        if (check(mid)) {
            l = mid;
        } else {
            r = mid - 1;
        }
    }
    return l;
}

C#

public class Solution {
    public int MaximumTastiness(int[] price, int k) {
        Array.Sort(price);
        int l = 0, r = price[price.Length - 1] - price[0];
        while (l < r) {
            int mid = (l + r + 1) >> 1;
            if (check(price, mid, k)) {
                l = mid;
            } else {
                r = mid - 1;
            }
        }
        return l;
    }

    private bool check(int[] price, int x, int k) {
        int cnt = 0, pre = -x;
        foreach (int cur in price) {
            if (cur - pre >= x) {
                ++cnt;
                pre = cur;
            }
        }
        return cnt >= k;
    }
}

...