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
這道題是之前那道 [Smallest Range I](https://www.cnblogs.com/grandyang/p/11318240.html) 的拓展,那道題說的是每個數字可以加上 [-K, K] 范圍內的任意一個數字,這道題說是每個數字必須加上K或者 —K,都是問新數組的最大值最小值之間的差值最小是多少。這兩個條件有顯著的區別,對於前一道題來說,非常的 flexible,因為可以加上 [-K, K] 范圍內的任意一個數字,就是說也可以加上0,從而數字保持不變,那么只需要對原數組的最大值最小值進行修改即可,而這道題所有數字都強制要進行修改,則只考慮最大值最小值顯然是不對的。來想想為什么不能直接對最小值加K,最大值減K,然后算差值。來看題目中的例子3,A = [1,3,6], K = 3,對最小值加K,得到4,對最大值減K,得到3,相減得到 -1,但實際上是不對的,因為中間的3也要進行加減操作,只能變成0或6,這樣相當於改變了新數組的最大值最小值,最終算下來的結果應該是3。博主其實也嘗試了暴力搜索法,即將原數組中的每個數字進行加K和減K,把得到的兩個新數字放到一個新數組中,最后遍歷新數組,找出最大值最小值並做差,結果超時了 Time Limit Exceeded!即便這只是一道 Medium 的題目,仍然不許我們用如此 Naive 的方法。只能另辟蹊徑了。
如果不考慮數字修改,那么原數組的最大值最小值之間的差值就是所求,這里可以當作結果 res 的初始值。由於每個數字都需要加K或者減K,為了使得新數組的最大值最小值的差值最小,應該盡量使原數組中的較小的數字加K,較大的數字減K,所以最好是先給原數組排個序,然后在數組的某個位置i為界限,將原數組分為兩段,前面所有的數字都加K,后面所有的數字都減K。則前半段 [0, i] 中的最大值是 A[i]+K,最小值是 A[0]+K,后半段 [i+1, n-1] 范圍內的最大值是 A[n-1]-K,最小值是 A[i+1]-K,所以整個數組的最大值是 A[i]+K 和 A[n-1]-K 中的較大值,最小值是 A[0]+K 和 A[i+1]-K 中的較小值,二者做差就是可能的結果了,遍歷所有的i,用每次計算出的差值來更新結果 res 即可,參見代碼如下:
``` class Solution { public: int smallestRangeII(vector
Github 同步地址:
https://github.com/grandyang/leetcode/issues/910
類似題目:
參考資料:
https://leetcode.com/problems/smallest-range-ii/
https://leetcode.com/problems/smallest-range-ii/discuss/173377/C%2B%2BJavaPython-Add-0-or-2-*-K
[LeetCode All in One 題目講解匯總(持續更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)