6359.最小化数对的最大差值-340

发布时间 2023-04-09 21:45:20作者: huangxk23

最小化数对的最大差值

给你一个下标从 0 开始的整数数组 nums 和一个整数 p 。请你从 nums 中找到 p 个下标对,每个下标对对应数值取差值,你需要使得这 p 个差值的 最大值 最小。同时,你需要确保每个下标在这 p 个下标对中最多出现一次。

对于一个下标对 i 和 j ,这一对的差值为 |nums[i] - nums[j]| ,其中 |x| 表示 x 的 绝对值 。

请你返回 p 个下标对对应数值 最大差值 的 最小值 。

示例 1:

输入:nums = [10,1,2,7,1,3], p = 2
输出:1
解释:第一个下标对选择 1 和 4 ,第二个下标对选择 2 和 5 。
最大差值为 max(|nums[1] - nums[4]|, |nums[2] - nums[5]|) = max(0, 1) = 1 。所以我们返回 1 。
示例 2:

输入:nums = [4,2,1,2], p = 1
输出:0
解释:选择下标 1 和 3 构成下标对。差值为 |2 - 2| = 0 ,这是最大差值的最小值。

提示:

\(1 <= nums.length <= 10^5\)
\(0 <= nums[i] <= 10^9\)
0 <= p <= (nums.length)/2

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimize-the-maximum-difference-of-pairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

二分答案+贪心。其中存在很多思考上的细节,自己对二分答案和区间也不是特别熟悉并不能解释得十分明白,加上最近时间还是有点紧张,先mark一下。

code

class Solution {
public:

    // 最小化最大值 -> 二分答案
    // 二分查找 -> 在一个具有二段性的数据上进行查找
    // 二分答案 -> 答案在一个区间内,在答案区间中二分直到找到最优的答案
    // 答案属于一个区间,区间对题目的某一个量具有单调性
    // 最小化最大值:二分最大值时在满足条件时尽量让答案更小也就是r = mid
    // 最大化最小值:二分最小值时在满足条件时尽量让答案更大也就是l = mid

    //例子:本题就是最小化最大值
    //答案区间就是自然数0 1 2 …… 9 ……
    //假如二分的中点是9 判断是否存在p个数对使得最大值为9
    //如果存在,显然应该往左侧区间二分否则往右侧区间二分
    //最小化最大值:答案ans, < ans 和>= ans 我们希望找到大于等于ans的左侧区间并且左侧区间都是可以满足p个数对的

    //恰好选p对数比较难写,选大于等于p对
    //贪心:如果前面两个可选,那么必选

    bool check(int mid,vector<int> & nums,int & p)
    {
        int cnt = 0,i = 0;
        while(i < nums.size() -1)
        {
            //满足就都选上
            if(nums[i+1] - nums[i] <= mid)
            {
                cnt ++;
                i += 2;
            }
            //不满足跳过
            else i ++;
        }

        return cnt >= p;
    }

    int minimizeMax(vector<int>& nums, int p) {

        sort(nums.begin(),nums.end());

        int n = nums.size();
        int l = 0,r = nums[n-1] - nums[0];

        while(l < r)
        {
            int mid = (l + r) / 2;
            if(check(mid,nums,p)) r = mid;
            else l = mid + 1;
        }

        return r;
    }
};