LeetCode破解之最小差值

84 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

题目描述

给你一个整数数组 nums,和一个整数 k 。

在一个操作中,您可以选择 0 <= i < nums.length 的任何索引 i 。将 nums[i] 改为 nums[i] + x ,其中 x 是一个范围为 [-k, k] 的整数。对于每个索引 i ,最多 只能 应用 一次 此操作。

nums 的 分数 是 nums 中最大和最小元素的差值。

在对 nums 中的每个索引最多应用一次上述操作后,返回 nums 的最低 分数 。

示例 1:

输入:nums = [1], k = 0 输出:0 解释:分数是 max(nums) - min(nums) = 1 - 1 = 0。

示例 2:

输入:nums = [0,10], k = 2 输出:6 解释:将 nums 改为 [2,8]。分数是 max(nums) - min(nums) = 8 - 2 = 6。

数学解法

思路很简单:把max,min假设成A,B两点AB两点同时射出一颗子弹,子弹最大射程为K,问子弹是否能碰撞。因为求得是最小得差值,所以减数应该尽可能大,被减数应该尽可能小。所以还要先对A数组排序,然后对最小值+K,对最大值-K,如果最小值+K>最大值-K,结果是0,否则结果就是差值。最后,我们只要遍历找最大值和最小值,求平均值。若最大值、最小值与平均值的差值都处于[-K,K]区间,表他们可以加或减某数后相等,则差值为0,否则最小值需尽可能大,最大值需尽可能小。

由题意已知,两颗子弹相向射出,两者最大射程 big=K+K。那就只有以下两种情况了。

- 只要最大射程大于AB两点距离,就一定可以碰撞,碰撞的时候就停下来了,两者掉在地上同一个地方,没有差值,返回0
- big <AB两点距离,那么两颗子弹最小的距离就是 AB-big,返回(max-min)-2K。
class Solution {
    public int smallestRangeI(int[] A, int K) {
       int max = A[0];int min = A[0];
        for (int i = 0; i < A.length; i++){
            if (A[i] > max){
                max = A[i];
            }
            if (A[i] < min){
                min = A[i];
            }
        }
        int MAX = max - K;
        int MIN = min + K;
        int ans = MAX - MIN;
        
        return ans<0?0:ans;
    }
}

注意点

题目有点绕,小心别被绕进去,多看两遍题目,看清楚在做。如果我们设K'是K的绝对值,那么A[i] - K'永远小于maxA-K',A[i] + K' 永远大于minA + K'。也就是说,A[i]与x的运算结果永远可以在(minA + K')和(maxA-K')之间,所以我们只需要让(minA + K')和(maxA-K')的差尽可能小就行了。因为,A[i与X的运算结果如果放到(minA + K')和(maxA-K')外面去,那么就是扩大了B中最大值与最小值的差值。