[LeetCode] 1217. Minimum Cost to Move Chips to The Same Position 玩籌碼



We have n chips, where the position of the ith chip is position[i].

We need to move all the chips to the same position. In one step, we can change the position of the ith chip from position[i] to:

  • position[i] + 2 or position[i] - 2 with cost = 0.
  • position[i] + 1 or position[i] - 1 with cost = 1.

Return the minimum cost needed to move all the chips to the same position.

Example 1:

Input: position = [1,2,3]
Output: 1
Explanation: First step: Move the chip at position 3 to position 1 with cost = 0.
Second step: Move the chip at position 2 to position 1 with cost = 1.
Total cost is 1.

Example 2:

Input: position = [2,2,2,3,3]
Output: 2
Explanation: We can move the two chips at position  3 to position 2. Each move has cost = 1. The total cost = 2.

Example 3:

Input: position = [1,1000000000]
Output: 1

Constraints:

  • 1 <= position.length <= 100
  • 1 <= position[i] <= 10^9

這道題說是有一堆籌碼,第i個籌碼所在的位置是 position[i],現在需要將所有的籌碼移動到一摞,規則是:左右移動兩個位置沒有 cost,左右移動一個位置需要花費1個 cost,問移動到同一摞需要的最少花費是多少。博主最先做的時候,一看既然是 Easy 題目,就別多想了,直接上暴力破解唄,找到 position 數組中的最大最小值,然后遍歷每一個位置,都統計所有籌碼移動到這個位置上的總花費,然后返回一個最小值,結果被 OJ 打臉,超時了 Time Limit Exceeded。直接過不去的就是題目中的例子3,這種方法要把范圍中的十億個位置都遍歷一遍,能不超時么。所以博主想了下,最終合成一摞的位置肯定是在某一個已經存在的籌碼的位置。

嚴謹的證明博主也不會,這里就大概說一下博主能想到的原因,若最終位置不在某個已經存在的籌碼的位置,那么看該位置距離任意一個籌碼的距離是否有偶數距離,有的話最終位置其實可以移動到那個籌碼的位置,因為偶數距離之間的移動沒有花費。若最終位置距離所有籌碼的位置均為奇數(則所有籌碼之間的距離均為偶數),那么該位置根本不應該成為最終位置,因為奇數距離都是有花費的。綜上所述,最終結果位置必定在某一個已經存在的籌碼的位置,那么這里其實就可以遍歷所有給定籌碼的位置,然后統計每個位置的花費。但其實這里還可以進一步優化,若有很多籌碼都在同一個位置,那么顯然按籌碼遍歷就不是很高效了,因為同一摞的籌碼可以一起移動,則花費可以一起計算。這里用一個 HashMap 統計每個位置上的籌碼個數,這樣就可以把相同位置上的籌碼摞到一起了。然后就可以遍歷每一個位置了,對於遍歷到的位置,再遍歷其他所有的位置,統計花費,這樣只要找到距離目標奇數位置,就可以把整個一摞的花費一起加上了。最后每次更新結果 res 即可,參見代碼如下:


解法一:

class Solution {
public:
    int minCostToMoveChips(vector<int>& position) {
        int res = INT_MAX;
        unordered_map<int, int> posCnt;
        for (int pos : position) ++posCnt[pos];
        for (auto &a : posCnt) {
            int sum = 0;
            for (auto &b : posCnt) {
                if ((b.first - a.first) % 2 == 0) continue; 
                sum += b.second;
            }
            res = min(res, sum);
        }
        return res;
    }
};

其實這道題還有更加簡潔高效的解法,因為距離為偶數的籌碼可以事先移動到一摞,而所有奇數位置的籌碼互相之間都是相距偶數的距離,所有偶數位置的籌碼互相之間也都是相距偶數的距離。這樣所有籌碼就可以在花費為0的情況下歸為相鄰的兩大摞,則總花費其實就是個數較小的那一摞,參見代碼如下:


解法二:

class Solution {
public:
    int minCostToMoveChips(vector<int>& position) {
        int even = 0, odd = 0;
        for (int pos : position) {
            (pos % 2 == 1) ? ++odd : ++even;
        }
        return min(odd, even);
    }
};

Github 同步地址:

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


類似題目:

Minimum Number of Operations to Move All Balls to Each Box


參考資料:

https://leetcode.com/problems/minimum-cost-to-move-chips-to-the-same-position/

https://leetcode.com/problems/minimum-cost-to-move-chips-to-the-same-position/discuss/398239/C%2B%2B-3-lines

https://leetcode.com/problems/minimum-cost-to-move-chips-to-the-same-position/discuss/398178/Detailed-Explanation-O(n)-or-O(1)-Everything-is-in-0-or-1


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

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



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