LeetCode刷题|#910 最小差值

#910 最小差值

1、题目

给定一个整数数组 A,对于每个整数 A[i],我们可以选择 x = -K 或是 x = K,并将 x 加到 A[i] 中。
在此过程之后,我们得到一些数组 B。
返回 B 的最大值和 B 的最小值之间可能存在的最小差值。

示例 1:

输入:A = [1], K = 0
输出:0
解释:B = [1]
示例 2:

输入:A = [0,10], K = 2
输出:6
解释:B = [2,8]
示例 3:

输入:A = [1,3,6], K = 3
输出:3
解释:B = [4,6,3]

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

提示:

  1. 1 <= A.length <= 10000
  2. 0 <= A[i] <= 10000
  3. 0 <= K <= 10000

2、解题思路

我们从示例中就可以看出,要想获得最小差值,就需要对数组A中较小的值加K,较大的值减K。这就可以尽可能地减小他们之间的差值。因此,我们先将原数组先排一下序。
在这里插入图片描述

然后,我们以一个元素为界,将较小值加K,将较大值减K。黑色是原数组,红色是新数组:
在这里插入图片描述

K值大小不同是,新数组的最值有所区别,当 K 很小的时候,就是下面的情况,显然红色的新数组里,最大值是 D,最小值是 A。
最小差值产生于分界处,最大差值产生于边界处。
在这里插入图片描述

当 K 很大的时候,就是下面的情况,显然红色新数组里,最大值是 B,最小值是 C。
最小差值产生于边界处,最大差值产生于分界处。
在这里插入图片描述

当我们选择在 i 这一点“切一刀”的时候,也就是 A[0] ~ A[i] 的元素都上移,A[i + 1] ~ A[A.length - 1] 的元素都下移。
此时 B 点的值是 A[i] + K,D 点的值是 A[A.length - 1] - K。
新数组的最大值要么是 B 点要么是 D 点,也就是说新数组的最大值是 Max(A[i] + K, A[A.length - 1] - K)。

同样道理,此时 A 点的值是 A[0] + K,C 点的值是 A[i + 1] - K。
新数组的最小值要么是 A 点要么是 C 点,也就是说新数组的最小值是 Min(A[0] + K, A[i + 1] - K)。

因此,题目需要的“新数组的最大值和最小值的差值”,就是 Max(A[i] + K, A[A.length - 1] - K) - Min(A[0] + K, A[i + 1] - K)。

K 的值是题目给出的固定值,因此如果我们想让上面这个算式的结果尽可能小的话,就要靠改变 i 的值,也就是思考究竟要在哪里“切这一刀”。因此我们挨个遍历一下所有可能的 i 的值,然后取上面算式的最小值即可。

作者:user83429423
链接:https://leetcode-cn.com/problems/smallest-range-ii/solution/tai-nan-liao-zhi-neng-hua-tu-ping-zhi-jue-by-user8/
来源:力扣(LeetCode)

3、代码实现

class Solution {
    public int smallestRangeII(int[] A, int K) {
        int n=A.length;
        Arrays.sort(A);
        int min=A[n-1]-A[0];//初始的min往大了取

        for(int i=0;i<n-1;i++){
            int high=Math.max(A[n-1]-K,A[i]+K);//最大点要么是左段的最右值,要么是右端的最右值
            int low=Math.min(A[i+1]-K,A[0]+K);//最小点要么是左段的最左值,要么是右段的最右值
            min=Math.min(min,high-low);
        }
        return min;
    }
}
  • 时间复杂度:O(N \log N),其中 NA 的长度。
  • 空间复杂度:O(1),额外空间就是自带排序算法的空间。

另sort()方法底层就是快排和归并排序,如果是基本数据类型就用快排,且是不稳定的,而对于基本数据类型,稳定性没有意义;如果是Object数据类型就是用的归并排序,且是稳定的。

展开阅读全文
©️2020 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值