这道题是为洗衣机阵列做负载均衡,题目难度为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;
- }
- };