Given an arrayAof integers, for each integerA[i]we need to chooseeither x = -K orx = K, and addxtoA[i](only once).
After this process, we have some arrayB.
Return the smallest possible difference between the maximum value ofB and the minimum value ofB.
Example 1:
Input: A = [1], K = 0Output: 0Explanation: B = [1]
Example 2:
Input: A = [0,10], K = 2Output: 6 Explanation: B = [2,8]
Example 3:
Input: A = [1,3,6], K = 3Output: 3Explanation: B = [4,6,3]
Note:
1 <= A.length <= 10000
0 <= A[i] <= 10000
0 <= K <= 10000
Solution
Approach 1: Linear Scan
Intuition
As inSmallest Range I, smallerA[i]will choose to increase their value ("go up"), and biggerA[i]will decrease their value ("go down").
Algorithm
We can formalize the above concept: ifA[i] < A[j], we don't need to consider whenA[i]goes down whileA[j]goes up. This is because the interval(A[i] + K, A[j] - K)is a subset of(A[i] - K, A[j] + K)(here,(a, b)fora > bdenotes(b, a)instead.)
That means that it is never worse to choose(up, down)instead of(down, up). We can prove this claim that one interval is a subset of another, by showing bothA[i] + KandA[j] - Kare betweenA[i] - KandA[j] + K.
For sortedA, sayA[i]is the largestithat goes up. ThenA[0] + K, A[i] + K, A[i+1] - K, A[A.length - 1] - Kare the only relevant values for calculating the answer: every other value is between one of these extremal values.
class Solution:
def smallestRangeII(self, A: List[int], K: int) -> int:
A.sort()
init_a, init_b = A[0], A[-1]
ans = init_b - init_a
for i in range(len(A) - 1):
a, b = A[i], A[i+1]
ans = min(ans, max(init_b-K, a+K) - min(init_a+K, b-K))
return ans
Complexity Analysis
Time Complexity:O(N \log N)O(NlogN), whereNNis the length of theA.
Space Complexity:O(1)O(1), plus the space used by the builtin sorting algorithm.