[leetcode] 517. Super Washing Machines
You have n super washing machines on a line. Initially, each washing machine has some dresses or is empty.
For each move, you could choose any m (1 ≤ m ≤ n) washing machines, and pass one dress of each washing machine to one of its adjacent washing machines at the same time .
Given an integer array representing the number of dresses in each washing machine from left to right on the line, you should find theminimum number of moves
Example1
Input: [1,0,5] Output: 3 Explanation: 1st move: 1 0 <-- 5 => 1 1 4 2nd move: 1 <-- 1 <-- 4 => 2 1 3 3rd move: 2 1 <-- 3 => 2 2 2
Example2
Input: [0,3,0] Output: 2 Explanation: 1st move: 0 <-- 3 0 => 1 2 0 2nd move: 1 2 --> 0 => 1 1 1
Example3
Input: [0,2,0] Output: -1 Explanation: It's impossible to make all the three washing machines have the same number of dresses.
Note:
- The range of n is [1, 10000].
- The range of dresses number in a super washing machine is [0, 1e5].
這道題是為洗衣機陣列做負載均衡,題目難度為Hard。
如果衣服總數不能被洗衣機總數整除,表明不能均分所有衣服,返回-1;如果能整除,拿avg表示最終每個洗衣機中衣服數。
如果我們能夠得到任意位置k上洗衣機最少需要的運算元,則遍歷整個陣列即可得到最終需要的最小運算元,因為所有位置互不相關,可以同時進行操作。
對位置k上的洗衣機來說,如果左邊k個洗衣機中(下標從0開始)原有衣服總數小於avg*k,表明左邊k個洗衣機作為整體最終需要從右邊洗衣機(包含位置k)中獲取衣服,而獲取衣服必定需要通過位置k的洗衣機,右邊同理。這裡拿lCnt表示位置k左邊所有洗衣機最終向右邊洗衣機(包含位置k)輸送的衣服數,如果lCnt小於0,表示左邊洗衣機最終需要從右邊洗衣機中獲取衣服,同理拿rCnt表示位置k右邊所有洗衣機最終向左邊洗衣機(包含位置k)中輸送的衣服數。lCnt和rCnt在知道了avg之後很容易計算,這樣通過判斷lCnt和rCnt的正負即可得出位置k上洗衣機的最小運算元。
-
如果lCnt>0 && rCnt>0
表明位置k需要同時從兩側獲取衣服,兩側可以同時進行,所以位置k上最小運算元為max(lCnt, rCnt);
-
如果lCnt<0 && rCnt<0
表明位置k同時向兩側輸出衣服,兩側不能同時進行,所以位置k上最小運算元為-lCnt-rCnt;
-
其他情況
表明位置k需要從一側獲取衣服,然後向另一側輸出衣服,兩側可以同時進行,所以位置k上最小運算元為max(abs(lCnt), abs(rCnt))。
遍歷整個陣列即可比較得出最終的最小操作次數。具體程式碼:
class Solution {
public:
int findMinMoves(vector<int>& machines) {
if(machines.empty()) return 0;
int n = machines.size(), minMv = INT_MIN, avg;
vector<int> sum(n+1, 0);
for(int i=0; i<n; ++i)
sum[i+1] = sum[i] + machines[i];
if(sum.back() % n) return -1;
avg = sum.back() / n;
for(int i=0; i<n; ++i) {
int lCnt = sum[i] - avg * i;
int rCnt = sum.back() - sum[i+1] - avg * (n - 1 - i);
if(lCnt > 0 && rCnt > 0)
minMv = max(minMv, max(lCnt, rCnt));
else if(lCnt < 0 && rCnt < 0)
minMv = max(minMv, 0 - lCnt - rCnt);
else
minMv = max(minMv, max(abs(lCnt), abs(rCnt)));
}
return minMv;
}
};