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
orposition[i] - 2
withcost = 0
.position[i] + 1
orposition[i] - 1
withcost = 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/