题目:
给你一个整数数组 nums
,和一个整数 k
。对于每个下标 i
(0 <= i < nums.length
),将 nums[i]
变成 nums[i] + k
或 nums[i] - k
。
nums
的 分数 是 nums
中最大元素和最小元素的差值。在更改每个下标对应的值之后,返回 nums
的最小 分数 。
示例 1:
输入:nums = [1], k = 0
输出:0
解释:分数 = max(nums) - min(nums) = 1 - 1 = 0 。
示例 2:
输入:nums = [0,10], k = 2
输出:6
解释:将数组变为 [2, 8] 。分数 = max(nums) - min(nums) = 8 - 2 = 6 。
示例 3:
输入:nums = [1,3,6], k = 3
输出:3
解释:将数组变为 [4, 6, 3] 。分数 = max(nums) - min(nums) = 6 - 3 = 3 。
提示:
1 <= nums.length <= 104
0 <= nums[i] <= 104
0 <= k <= 104
思路:
由于每个值都要进行操作,所以利用贪心处理
排序 + 贪心枚举分界点。每个数位必须操作一次,贪心思路是让大值变小、小值变大,即排序后以某个点i为分界线,i及其左侧全+k,i右侧全-k,枚举i记录最小极差即可。
代码:
class Solution {
public:
int smallestRangeII(vector<int>& nums, int k) {
// 排序 + 贪心枚举
sort(nums.begin(), nums.end());
// diff初值为nums全+k或全-k的极差,后续枚举分界点i。
int n = nums.size(), diff = nums[n - 1] - nums[0];
// 枚举分界点,i及左侧均 + k,右侧i + 1开始均-k,
// 那么max取左半段最大值(nums[i] + k)与右半段最大值(nums[n-1] - k)中较大者,
// min取左半段最小值(nums[0] + k)与右半段最小值(nums[i+1] - k)中较小者。
for (int i = 0; i < n - 1; i++) {
int R = max(nums[i] + k, nums[n - 1] - k);
int L = min(nums[0] + k, nums[i + 1] - k);
diff = min(diff, R - L);
}
return diff;
}
};