题目
给你一个整数数组 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 <= 10^4
0 <= nums[i] <= 10^4
0 <= k <= 10^4来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/smallest-range-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
将数组排序,对于较小的值我们希望其加上k变大,对于较大的值我们希望其减去k变小,这样可以缩小两个最值的差距。
而且,对于某一下标i,如果nums[i]增加k,nums[i+1]减去k,那么i左侧的一定都是加k,i+1右侧的一定是减k。这一点比较好理解也可以证明。
如果出现上面的情况,那么就会出现当nums[i]<nums[j], i<j, 有将nums[i]减k,将nums[j]加k的情况,将较小的值变得更小,较大的值变得更大,这是没有意义的,获得的结果肯定不会优于将小值增大,将大值减小。
因此,可以枚举下标i,在此之前(包括i)所有数都加k,之后的减k。
代码
class Solution {
public int smallestRangeII(int[] nums, int k) {
Arrays.sort(nums);
int n = nums.length;
int minNum = 0;
int maxNum = 0;
int ans = nums[n - 1] - nums[0];
// i下标是最后一个加k的,即从i+1开始的数都减k
for (int i = 0; i < n - 1; i++) {
maxNum = Math.max(nums[i] + k, nums[n - 1] - k);
minNum = Math.min(nums[0] + k, nums[i + 1] - k);
ans = Math.min(ans, maxNum - minNum);
}
return ans;
}
}