leetcode 910. 最小差值 II —— 贪心算法

910. 最小差值 II

题目来源:力扣(LeetCode)
https://leetcode-cn.com/problems/smallest-range-ii/

解题思路:

这道题的题意是A数组中的每个元素要么加K、要么减K,只能进行其中的一个操作。在每个元素操作完后就构成一个新的数组B,要求使B中数组元素的最大值与最小值的差值最小。

对于这道题,我们先来考虑所有情况:假设两个数x、y,且x<y。

1、x、y都加K与都减K的结果与原数组A中的最大最小元素的差值一样。算一种情况。 即 (y+k)-(x+k)=y-k 或 (y-k)-(x-k)=y-k 。
2、y加k、x减k。即(y+k)-(x-k)=y-x+2k。
3、y减k、x加k。即(y-k)-(x+k)=y-x-2k。

若k>0,我们只需要考虑第三种情况。只有第三种情况下的值最小(可能与第一种一样)。

那么我们可以想,先将原数组进行从小到大排序,这样得到原数组中最小元素A[0]与最大元素A[n-1]。此时最大与最小元素差值为A[n-1]-A[0]。此时包括第一种情况。

对于第二种情况,当大的元素加K而小的元素减K,最终会导致新数组元数中的最大值与最小值之差比原数组的结果大,故不需要考虑。

最终只有第三种情况需要考虑,即大的元素减K,小的元素加K,这种情况才可能出现比原数组的结果更小的结果。注意:差值最大不会大于A[n-1]-A[0],只能比A[n-1]-A[0]小。

现在如何根据第三种情况使结果最小。首先根据排序后的数组,我们得到第一种情况的解;现在再遍历排序后的数组的相邻两位数,如A[i]、A[i+1],有A[i]<A[i+1]。A[i]+k一定会大于A[0]+k,只需要考虑A[i]+k与A[n-1]-k的大小,要在这两者中选一个最大的;A[i+1]-k一定小于A[n-1]-k,只需要考虑A[i+1]-k与A[0]+k的大小,要在这两者中选一个最小的。这样就得到一个新数组中的结果。

代码:

public int smallestRangeII(int[] A, int K) {
    // 先对数组进行排序
    Arrays.sort(A);
    int n = A.length;  // 数组长度
    // 排序后,A[0]为数组最小值,A[n-1]为数组最大值。求得原数组中最大与最小值之差
    int res = A[n-1]-A[0];
    // 遍历数组中的每相邻的两个元素
    for (int i = 0; i < n-1; i++) {
        int max = Math.max(A[n-1]-K,A[i]+K);
        int min = Math.min(A[0]+K,A[i+1]-K);
        int error = max - min;
        // 取小的结果。
        res = Math.min(res,error);
    }
    return res;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值