雙周賽98。這題很奇妙,第一眼沒想法就跳過不做。回來才發現被擺一道,但又沒有一次做對,又氣又好笑。

題目

輸入整數陣列nums。

  • nums的low為所有 nums[i] - nums[j] 中的最小值,其中0 <= i < j < nums.length
  • nums的high為所有 nums[i] - nums[j] 中的最大值,其中0 <= i < j < nums.length
  • nums的總分lowhigh的加總

你可以將nums中最多兩個元素改變,使得總分最小化。

求改變元素後,nums的最小可能總分

解法

總分由low和high組成,要使總分變小可以選擇減少low或是減少high。
減少low有個穩定的方法:隨便挑選一個數字,換成某一個數字。這樣low就會是0。
減少high則可以是將nums中最小值變大,或是將最大值變小。

就拿例題二來想想:

nums = [5,3,2]
排序後 = [2,3,5]
若將最小值2變大,新的最小值肯定會是原第二小值,也就是3
若將最大值5變小,新的最大值肯定會是原第二大值,也就是3

那被改變的最大/最小值要變成多少?

nums = [2,3,5]
如果把2變3,得到[3,3,5],high為5-3
如果把2變4,得到[3,4,5],high為是5-3

可見最小值變成超過次小值的數並沒有意義。但是!把最小值變成次小值可以順帶把low也變成0
赫然發現low根本是個假議題,根本不需要去管他,自然會變成0。

問題轉換成改變兩個數使high最小
延續剛才的結論,我們可以從最小/大值下手。那如果最大值和最小值一樣怎麼辦?

nums = [1,2,3,..,5,5,5]
這種情況下改變最大值也沒用,但我們還是需要改兩個數
乾脆把最小/次小值通通變成第三小值
nums = [3,3,3,..,5,5,5]

所以最佳解必定為以下三種之一:

  1. 最小變成次小 + 最大變成次大
  2. 最小、次小變成第三小
  3. 最大、次大便呈第三大

最後檢查測資範圍,題目保證nums至少有三個數,因此不必擔心出界。

瓶頸在於排序,時間複雜度O(N log N)。空間複雜度O(1)。

class Solution:
    def minimizeSum(self, nums: List[int]) -> int:
        nums.sort()

        ans=min(
                nums[-2]-nums[1],
                nums[-1]-nums[2],
                nums[-3]-nums[0]
               )
        
        return ans