Medium
题目描述
给你一个整数数组 nums。
nums的低分是任意两个整数之间的最小绝对差值。nums的高分是任意两个整数之间的最大绝对差值。nums的分数是高分和低分的总和。
返回改变 nums 中两个元素后的最小分数。
示例 1:
输入:nums = [1,4,7,8,5]
输出:3
解释:
将 nums[0] 和 nums[1] 改为 6,使 nums 变为 [6,6,7,8,5]。
低分是最小绝对差值:|6 - 6| = 0。
高分是最大绝对差值:|8 - 5| = 3。
高分和低分的总和是 3。
示例 2:
输入:nums = [1,4,3]
输出:0
解释:
将 nums[1] 和 nums[2] 改为 1,使 nums 变为 [1,1,1]。
最大绝对差值和最小绝对差值的总和是 0。
约束条件:
3 <= nums.length <= 10^51 <= nums[i] <= 10^9
解题思路
这是一道贪心算法题目。我们需要理解两个关键点:
最小绝对差值(低分):要让最小绝对差值尽可能小,最好的策略是让两个相邻元素变得相等,这样最小差值就是0。
最大绝对差值(高分):要让最大绝对差值尽可能小,需要缩小整个数组的范围,即减少最大值和最小值之间的差距。
核心思路:
- 对数组进行排序,这样最大值和最小值分别在两端
- 我们可以改变两个元素,最优策略是改变数组的极值(最大或最小的几个元素)
- 有三种主要策略:
- 改变两个最小值:让它们等于第三小的值
- 改变两个最大值:让它们等于第三大的值
- 改变一个最小值和一个最大值:分别等于第二小和第二大的值
分析三种情况:
排序后,设数组为 [a, b, c, ..., x, y, z]
- 情况1:改变
a, b为c,新的高分是z - c,低分是 0 - 情况2:改变
y, z为x,新的高分是x - a,低分是 0 - 情况3:改变
a为b,改变z为y,新的高分是y - b,低分是 0
取三种情况的最小值即可。
代码实现
class Solution {
public:
int minimizeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
int n = nums.size();
// 三种策略的结果
int option1 = nums[n-1] - nums[2]; // 改变两个最小值
int option2 = nums[n-3] - nums[0]; // 改变两个最大值
int option3 = nums[n-2] - nums[1]; // 改变一个最小值和一个最大值
return min({option1, option2, option3});
}
};
class Solution:
def minimizeSum(self, nums: List[int]) -> int:
nums.sort()
n = len(nums)
# 三种策略的结果
option1 = nums[n-1] - nums[2] # 改变两个最小值
option2 = nums[n-3] - nums[0] # 改变两个最大值
option3 = nums[n-2] - nums[1] # 改变一个最小值和一个最大值
return min(option1, option2, option3)
public class Solution {
public int MinimizeSum(int[] nums) {
Array.Sort(nums);
int n = nums.Length;
// 三种策略的结果
int option1 = nums[n-1] - nums[2]; // 改变两个最小值
int option2 = nums[n-3] - nums[0]; // 改变两个最大值
int option3 = nums[n-2] - nums[1]; // 改变一个最小值和一个最大值
return Math.Min(Math.Min(option1, option2), option3);
}
}
var minimizeSum = function(nums) {
nums.sort((a, b) => a - b);
const n = nums.length;
// 三种策略的结果
const option1 = nums[n-1] - nums[2]; // 改变两个最小值
const option2 = nums[n-3] - nums[0]; // 改变两个最大值
const option3 = nums[n-2] - nums[1]; // 改变一个最小值和一个最大值
return Math.min(option1, option2, option3);
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(n log n) | 主要消耗在排序操作上 |
| 空间复杂度 | O(1) | 只使用常数额外空间(排序为原地排序) |