中等
最小化两组极差之和
排序贪心数组
相关算法文章:
题目描述
给定 n 个整数,需要将它们任意分成两组,且两组都不能为空。
对于一组数,它的极差定义为该组中的最大值减去最小值。目标:最小化这两个极差之和,即 (max1 - min1) + (max2 - min2)。输出这个最小值。
数据范围:
- 1 ≤ n ≤ 10⁵
- 数组元素为整数
示例
示例1:
输入:5,[10,1,5,3,8]
输出:6
说明:划分为 [10,8] 和 [1,5,3] 两组:左极差 = 5-1 = 4,右极差 = 10-8 = 2,总和 = 6。
示例2:
输入:5,[1,1,9,1,9]
输出:0
说明:分组为 [1,1,1] 和 [9,9],两组的极差均为 0,和为 0。
示例3:
输入:2,[1,2]
输出:0
说明:分组为 [1] 和 [2],两组极差均为 0,和为 0。
解题思路
关键洞察: 排序后,最优分组必然是将数组在某个位置“切开”。
排序后,数组变为 [a₀, a₁, ..., a_{n-1}]。
假设第 1 组包含 a₀(最小值),第 2 组包含 a_{n-1}(最大值),那么:
- 第 1 组的极差至少为 0
- 第 2 组的极差至少为 0
最优分组策略: 排序后,在第 i 个位置(1 ≤ i < n)切开:
- 第 1 组:
[a₀, ..., a_{i-1}],极差 =a_{i-1} - a₀ - 第 2 组:
[a_i, ..., a_{n-1}],极差 =a_{n-1} - a_i - 总极差 =
(a_{i-1} - a₀) + (a_{n-1} - a_i)
遍历所有可能的切分点 i,取最小值。
特例: n ≤ 2 时,直接返回 0(两组各一个元素,极差均为 0)。
代码实现
function getResult(n, nums) {
if (n <= 2) return 0;
nums.sort((a, b) => a - b);
let min = Infinity;
for (let i = 1; i < n; i++) {
const leftRes = nums[i - 1] - nums[0];
const rightRes = nums[n - 1] - nums[i];
min = Math.min(min, leftRes + rightRes);
}
return min;
}
复杂度分析
- 时间复杂度: O(n log n),排序占主导。遍历切分点为 O(n)。
- 空间复杂度: O(1),原地排序,常数额外空间。
示例输入 / 输出
下面给出一组输入输出示例,便于对照题意与结果。
编号 min-range-sum难度 中等
输入
5,[10,1,5,3,8]
输出
6