问题描述
小F手里有一个长度为nn的数组,他可以选择删除数组中的任意两个元素,并将它们的和作为一个新元素放回数组中。他最多可以进行一次这样的操作。小F的目标是使得数组的极值(即数组最大值减去最小值)尽可能小。现在你需要帮助小F计算出在最优操作下,数组能达到的最小极值。
问题分析
本题的目标是通过删除两个数组元素并用它们的和替换,来最小化数组的极值(最大值减去最小值)。可以进行最多一次这样的操作。
以下是问题的几个关键点:
-
初始极值计算:
- 极值为数组最大值减去最小值。如果不进行任何操作,极值为原始数组的最大值减去最小值。
-
替换操作的影响:
- 选择删除两个元素 aa 和 bb,将它们的和 a+ba+b 放入数组中。这可能会影响数组的最大值或最小值,进而影响极值。
-
目标:
- 通过一次操作,尝试最小化新的极值。
解题思路
-
不进行操作的极值:
- 原始极值计算为: 原始极值=max(nums)−min(nums)\text{原始极值} = \max(\text{nums}) - \min(\text{nums})
-
一次操作后的影响:
- 如果删除两个较小的元素,将它们的和放入数组中,可能提升数组的最小值。
- 如果删除两个较大的元素,将它们的和放入数组中,可能降低数组的最大值。
- 还可以删除一个较小和一个较大的元素,从而同时影响最大值和最小值。
-
方案枚举:
-
考虑删除的两种情形:
- 删除数组中的两个最小值 a,ba, b 或两个最大值 c,dc, d。
- 删除数组中的最小值和最大值 a,da, d。
-
逐一计算这三种方案下的极值,并取最小值。
-
-
实现步骤:
- 将数组排序以便快速访问最小值和最大值。
- 根据上述操作计算不同情形下的极值。
- 返回最小极值。
实现代码
以下是 Python 的实现:
def minimize_extreme(nums):
# 排序数组
nums.sort()
n = len(nums)
# 初始极值(不操作)
original_extreme = nums[-1] - nums[0]
# 情形 1:删除两个最小值
if n > 2:
extreme_case1 = nums[-1] - (nums[0] + nums[1])
else:
extreme_case1 = original_extreme
# 情形 2:删除两个最大值
if n > 2:
extreme_case2 = (nums[-2] + nums[-1]) - nums[0]
else:
extreme_case2 = original_extreme
# 情形 3:删除最小值和最大值
if n > 2:
extreme_case3 = nums[-2] - nums[1]
else:
extreme_case3 = original_extreme
# 返回最小的极值
return min(original_extreme, extreme_case1, extreme_case2, extreme_case3)
示例测试
示例 1
输入:
nums = [4, 2, 1, 10]
输出:
5
过程分析:
- 原始极值为 10−1=910 - 1 = 9。
- 情形 1:删除 1,21, 2,加入 1+2=31+2=3,极值为 10−3=710 - 3 = 7。
- 情形 2:删除 10,410, 4,加入 10+4=1410+4=14,极值为 14−1=1314 - 1 = 13。
- 情形 3:删除 1,101, 10,加入 1+10=111+10=11,极值为 4−2=24 - 2 = 2。
- 最优极值为 min(9,7,13,2)=2 \min(9, 7, 13, 2) = 2。
时间复杂度与空间复杂度
时间复杂度
- 排序操作:O(nlogn)O(n \log n)。
- 常数级操作(计算三种情形):O(1)O(1)。
- 总复杂度为 O(nlogn)O(n \log n)。
空间复杂度
- 使用原地排序,额外空间需求为 O(1)O(1)。
总结
本题的关键在于:
- 理解极值的定义和替换操作对极值的潜在影响。
- 列举所有可能的操作情形,结合排序后的最小值和最大值计算结果。
- 在操作和不操作的所有方案中取最优解。
通过排序和简单计算,算法高效且易于实现。