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)
.html
After this process, we have some array B
.git
Return the smallest possible difference between the maximum value of B
and the minimum value of B
.github
Example 1:數組
Input: A = [1], K = 0 Output: 0 Explanation: B = [1]
Example 2:flex
Input: A = [0,10], K = 2 Output: 6 Explanation: B = [2,8]
Example 3:this
Input: A = [1,3,6], K = 3 Output: 3 Explanation: B = [4,6,3]
Note:code
1 <= A.length <= 10000
0 <= A[i] <= 10000
0 <= K <= 10000
這道題是以前那道 Smallest Range I 的拓展,那道題說的是每一個數字能夠加上 [-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 的方法。只能另闢蹊徑了。htm
若是不考慮數字修改,那麼原數組的最大值最小值之間的差值就是所求,這裏能夠看成結果 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 便可,參見代碼以下:blog
class Solution { public: int smallestRangeII(vector<int>& A, int K) { sort(A.begin(), A.end()); int n = A.size(), res = A[n - 1] - A[0]; int left = A[0] + K, right = A[n - 1] - K; for (int i = 0; i < n - 1; ++i) { int high = max(right, A[i] + K); int low = min(left, A[i + 1] - K); res = min(res, high - low); } return res; } };
Github 同步地址:leetcode
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