【力扣周赛】第340场周赛

【力扣周赛】第340场周赛

    • 2616:最小化数对的最大差值
      • 题目描述
      • 解题思路

2616:最小化数对的最大差值

题目描述

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

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

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

1 <= nums.length <= 105
0 <= nums[i] <= 109
0 <= p <= (nums.length)/2。

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

解题思路

最小化数对的最大差值:最直观的想法是,最小化最大差值或者最大化最小差值是二分法的经典题目。首先将数组排序,使得相邻的数字相差较小,然后由于每个数最多取一次,故每次i+=2。使用二分法,首先确定左边界与右边界,初始左边界是最小差值为0,初始右边界是最大差值为排序后数组的最大值与最小值之差,然后取左闭右闭区间[left,right],故循环条件是left<=right,首先求中间值mid,然后求区间内差值小于等于mid的数值对对数cnt,如果cnt大于等于给定的p,那么就需要缩小差值区间,令right=mid-1,反之则需要扩大差值区间,令left = mid+1,最后返回left即可。注意,因为是最小差值的最大化,所以当差值区间满足要求的数值对对数cnt等于给定p,这样是最佳的,可是为什么等于后仍需要将right设置为mid-1呢?假设mid已经是刚好等于,此时right变为mid-1,则必定有cnt

递归的两种模板:

1、[left,right]
left<=right  [right,right]区间有意义
right=mid-1
left=mid+1

2、[left,right)
left
int minimizeMax(vector& nums, int p) 
{
    // 排序数组
    sort(nums.begin(),nums.end());
    // 最小差值0 最大差值是排序数组最后一个数与第一个数的差值
    int left=0,right=nums[nums.size()-1]-nums[0];
    // 闭区间[left,right]
    while(left<=right)
    {
       // 中间值
       int mid=left+(right-left)/2;
       // 统计满足的数值对对数
       int cnt=0;
       // 遍历数组统计满足的数值对对数
       for(int i=0;i=p)
           right=mid-1;
       else
           left=mid+1;
    }
    return left;
}

你可能感兴趣的:(力扣周赛,leetcode,算法,数据结构)