[LeetCode] 910. 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. 1 <= A.length <= 10000
  2. 0 <= A[i] <= 10000
  3. 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 & 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 同步地址:

https://github.com/grandyang/leetcode/issues/910


類似題目:

Smallest Range I


參考資料:

https://leetcode.com/problems/smallest-range-ii/

https://leetcode.com/problems/smallest-range-ii/discuss/173377/C%2B%2BJavaPython-Add-0-or-2-*-K

https://leetcode.com/problems/smallest-range-ii/discuss/173389/simple-C%2B%2B-solution-with-explanation


[LeetCode All in One 題目講解匯總(持續更新中...)](https://www.cnblogs.com/grandyang/p/4606334.html)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM