题目
假设有 n 台超级洗衣机放在同一排上。开始的时候,每台洗衣机内可能有一定量的衣服,也可能是空的。
在每一步操作中,你可以选择任意 m (1 ≤ m ≤ n) 台洗衣机,与此同时将每台洗衣机的一件衣服送到相邻的一台洗衣机。
给定一个非负整数数组代表从左至右每台洗衣机中的衣物数量,请给出能让所有洗衣机中剩下的衣物的数量相等的最少的操作步数。如果不能使每台洗衣机中衣物的数量相等,则返回 -1。
实现
class Solution {
public int findMinMoves(int[] machines) {
int sum = 0;
for (int i = 0; i < machines.length; i++) {
sum += machines[i];
}
if (sum % machines.length != 0) {
return -1;
}
int avg = sum / machines.length;
int leftRest = 0;
int rightRest = 0;
int leftSum = 0;
int ans = 0;
//如果来到了数组的某个位置i,左侧应该有i * avg台洗衣机
//右侧应该有(machines.length - i - 1) * avg台机器,这是理论上应该有的机器
//而左侧实际的机器是leftSum,如果leftRest为正,表示左侧需要抛出多少台机器
//若果为负,表示左侧需要添加多少台机器,右侧也是同样的道理
//此时的情况:
//如果leftRest和rightRest都为负,则表示左侧需要添加,右侧也需要添加,肯定是i位置多了
//需要往两侧放衣服,但是一次只能放一件,所以至少需要Math.abs(leftRest) + Math.abs(rightRest)轮
//左侧右侧都是正(i位置可以同时从两侧接受衣服),至少需要Math.abs(leftRest) + Math.abs(rightRest)
//如果左侧正,右侧负,或者右侧正,左侧负,左侧传递到i,i传递到右侧,然后左侧在传递给i
//第二种情况同理也是需要Math.abs(leftRest) + Math.abs(rightRest)
for (int i = 0; i < machines.length; i++) {
leftRest = leftSum - i * avg;
rightRest = sum - leftSum - machines[i] - (machines.length - i - 1) * avg;
if (leftRest < 0 && rightRest < 0) {
ans = Math.max(ans, Math.abs(leftRest) + Math.abs(rightRest));
} else {
ans = Math.max(ans, Math.max(Math.abs(leftRest), Math.abs(rightRest)));
}
leftSum += machines[i];
}
return ans;
}
}