2616-最小化数对的最大差值
给你一个下标从 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 <= 105
0 <= nums[i] <= 109
0 <= p <= (nums.length)/2
本题视频讲解
见【周赛 340】 。
前置知识:二分
见 二分查找【基础算法精讲 04】 。
提示 1
看到「最大化最小值」或者「最小化最大值」就要想到二分答案,这是一个固定的套路。
为什么?一般来说,二分的值越大,越能/不能满足要求;二分的值越小,越不能/能满足要求,有单调性,可以二分。
更多题目见文末的题单。
提示 2
二分数对中的最大差值 mx。
由于下标和答案无关,可以先排序。为了让匹配的数对尽量多,应尽量选相邻的元素,这样更能满足要求。例如 [1,2,3,4],如果 1,3 匹配,2,4 匹配,最大差值是 2;而如果 1,2 相邻匹配,3,4 相邻匹配,最大差值只有 1。
我们来算一算最多能匹配多少个数对:
- 如果可以选 nums}[0] 和 nums}[1],那么答案等于「n-2 个数的最多数对个数」+1。
- 如果不选 nums}[0],那么答案等于「n-1 个数的最多数对个数」。
- 这两种情况取最大值。
这看上去很像 198. 打家劫舍 ,可以用动态规划实现。
也可以用贪心做:
- 注意到,「n-1 个数的最多数对个数」不会超过「n-3 个数的最多数对个数」+1。这里 +1 表示选 nums}[1] 和 nums}[2]。
- 由于「n-2 个数的最多数对个数」\ge「n-3 个数的最多数对个数」,所以如果可以选 nums}[0] 和 nums}[1],那么直接选就行。
- 依此类推,不断缩小问题规模。所以遍历一遍数组就能求出最多数对个数,具体见代码。
1 | class Solution: |
1 | class Solution { |
1 | class Solution { |
1 | func minimizeMax(nums []int, p int) int { |
复杂度分析
- 时间复杂度:O(n\log n + n\log U),其中 n 为 nums 的长度,U=\max(\textit{nums})-\min(\textit{nums})。
- 空间复杂度:O(1)。忽略排序时的栈空间,仅用到若干额外变量。
二分答案·题单
二分答案
- 875. 爱吃香蕉的珂珂
- 1283. 使结果不超过阈值的最小除数
- 2187. 完成旅途的最少时间
- 2226. 每个小孩最多能分到多少糖果
- 1870. 准时到达的列车最小时速
- 1011. 在 D 天内送达包裹的能力
- 2064. 分配给商店的最多商品的最小值
- 1760. 袋子里最少数目的球
- 1482. 制作 m 束花所需的最少天数
- 1642. 可以到达的最远建筑
- 1898. 可移除字符的最大数目
- 778. 水位上升的泳池中游泳
- 2258. 逃离火灾
最小化最大值
最大化最小值
Comments