1. 程式人生 > >[leetcode] 517. Super Washing Machines

[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

 to make all the washing machines have the same number of dresses. If it is not possible to do it, return -1.

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:

  1. The range of n is [1, 10000].
  2. 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;
    }
};