题目来源:https://leetcode.com/contest/weekly-contest-103/problems/smallest-range-ii/
问题描述
Given an array A
of integers, for each integer A[i]
we need to choose either x = -K
or x = K
, and add x
to A[i]
(only once).
After this process, we have some array B
.
Return the smallest possible difference between the maximum value of B
and the minimum value of B
.
Example 1:
Input: A = [1], K = 0 Output: 0 Explanation: B = [1]
Example 2:
Input: A = [0,10], K = 2 Output: 6 Explanation: B = [2,8]
Example 3:
Input: A = [1,3,6], K = 3 Output: 3 Explanation: B = [4,6,3]
Note:
1 <= A.length <= 10000
0 <= A[i] <= 10000
0 <= K <= 10000
------------------------------------------------------------
题意
给定一个数列A和一个正整数K,规定数列B的生成方式为:A中的每个数必须加上K或减去K得到B中相应元素。问如此得到所有的数列B,最大值和最小值之差最小是多少?
------------------------------------------------------------
思路
本题实际上就是要解决得到数列B的过程中,数列A中哪些数需要+K,哪些数需要-K的问题。本蒟蒻想了很久想不出来这个问题,最后参考了这篇博文【leetcode】910. Smallest Range II才会的。在此感谢这位博主啦。
如果直接枚举,复杂度为O(2^N)。考虑利用单调性降低枚举的复杂度。首先将A排序,不妨设A升序排列,记作A+。对于A+,如果希望最小化最大值与最小值之差,有如下两条性质:
1. 若A+[i]需要+K,则A+[i]之前的数也都需要+K
2. 若A+[i]需要-K,则A+[i]之后的数也都需要-K
根据上述两条性质,我们总能在A+中找到一个i, 是的A+[i]以及A+[i]之前的数都+K,A+[i]之后的数都-K,这样,枚举的复杂度就降低到了O(N). 另排序的复杂度为O(NlogN),故总复杂度为O(NlogN).
------------------------------------------------------------
代码
class Solution {
public:
const int inf = 0x3f3f3f3f;
int smallestRangeII(vector& A, int K) {
int minv = inf, maxv = -inf, i, len = A.size(), left, right, ans = inf;
sort(A.begin(), A.end());
for (i=0; i