录制下载而不是收藏资料的原因
2026/1/8 20:54:48
给你一个整数数组nums和一个整数k。你可以选择数组中的任一元素并将其替换为[num - k, num + k]范围内的任意整数。
在应用此操作至多一次后,求数组中最大值和最小值之间的最小可能差值。
示例:
输入: nums = [1], k = 0 输出: 0 解释: 数组只有一个元素,最大值和最小值相同,差值为0。 输入: nums = [0,10], k = 2 输出: 6 解释: 将0变为2,将10变为8,数组变为[2,8],差值为6。 输入: nums = [1,3,6], k = 3 输出: 0 解释: 将 nums 改为 [4,4,4]。分数是 max(nums) - min(nums) = 4 - 4 = 0。贪心策略:
maxNum和最小值minNumk(变为minNum + k)k(变为maxNum - k)minNum + k >= maxNum - k,说明可以将所有元素调整到同一个值,差值为0(maxNum - k) - (minNum + k) = maxNum - minNum - 2*kclassSolution{/** * 计算应用操作后数组最大值和最小值的最小可能差值 * * @param nums 输入整数数组 * @param k 可调整的范围参数 * @return 最小可能差值 */publicintsmallestRangeI(int[]nums,intk){// 找到数组中的最大值和最小值intminNum=nums[0];intmaxNum=nums[0];for(intnum:nums){minNum=Math.min(minNum,num);maxNum=Math.max(maxNum,num);}// 计算调整后的最小差值// 最小值最多可以增加到 minNum + k// 最大值最多可以减少到 maxNum - kintadjustedMin=minNum+k;intadjustedMax=maxNum-k;// 如果调整后的最小值 >= 调整后的最大值,说明可以完全重合,差值为0if(adjustedMin>=adjustedMax){return0;}// 否则返回调整后的差值returnadjustedMax-adjustedMin;}}classSolution{/** * 优化 * * @param nums 输入整数数组 * @param k 可调整的范围参数 * @return 最小可能差值 */publicintsmallestRangeI(int[]nums,intk){intminNum=Arrays.stream(nums).min().getAsInt();intmaxNum=Arrays.stream(nums).max().getAsInt();returnMath.max(0,maxNum-minNum-2*k);}}输入:nums = [1,3,6], k = 3
minNum = 1,maxNum = 6adjustedMin = 1 + 3 = 4adjustedMax = 6 - 3 = 34 >= 3,返回0输入:nums = [0,10], k = 2
minNum = 0,maxNum = 10adjustedMin = 0 + 2 = 2adjustedMax = 10 - 2 = 82 < 8,返回8 - 2 = 6输入:nums = [1], k = 0
minNum = 1,maxNum = 1adjustedMin = 1 + 0 = 1adjustedMax = 1 - 0 = 11 >= 1,返回0publicstaticvoidmain(String[]args){Solutionsolution=newSolution();// 测试用例1:单元素数组int[]nums1={1};System.out.println("Test 1: "+solution.smallestRangeI(nums1,0));// 0// 测试用例2:标准示例int[]nums2={0,10};System.out.println("Test 2: "+solution.smallestRangeI(nums2,2));// 6// 测试用例3:可以完全重合int[]nums3={1,3,6};System.out.println("Test 3: "+solution.smallestRangeI(nums3,3));// 0// 测试用例4:k为0(无法调整)int[]nums4={2,7,2};System.out.println("Test 4: "+solution.smallestRangeI(nums4,0));// 5// 测试用例5:大k值int[]nums5={1,3,6};System.out.println("Test 5: "+solution.smallestRangeI(nums5,10));// 0// 测试用例6:负数int[]nums6={-1,-3,-6};System.out.println("Test 6: "+solution.smallestRangeI(nums6,2));// 0// 测试用例7:大数组int[]nums7={100,200,300,400,500};System.out.println("Test 7: "+solution.smallestRangeI(nums7,50));// 300// 测试用例8:k刚好让差值为0int[]nums8={1,5};System.out.println("Test 8: "+solution.smallestRangeI(nums8,2));// 0}贪心策略:
边界处理:
minNum + k >= maxNum - k时,差值为0数学公式:
max(0, maxNum - minNum - 2*k)特殊情况:
为什么不需要考虑中间元素的调整?
为什么是2*k而不是k?
k + k = 2*k的差值