题目
有n个洗衣机,一共有m件衣服,每个洗衣机都放了任意数量衣服,每轮每个洗衣机可以向相邻洗衣机移动一个衣服,求最少多少轮可以使得所有洗衣机内的衣服数量一样
- 对于 i 位置的洗衣机,假设 i 位置左边一共有 m 件衣服,l 台洗衣机,i 位置右边一共有 n 件衣服,r 台洗衣机,因为如果需要每台洗衣机衣服一致,所以总的衣服数量一定能够整除洗衣机数量,假设每台洗衣机平均分到 k 件衣服,如果整出左边理想衣服数量为lk,右边理想数量为yk
- 如果 m-lk < 0 说明左边需要 |m-lk|数量衣服,m-lk>0,说明左边需要向右传递|m-lk|数量衣服,n-rk同理
- 那么对于 i 位置就有三种情况
- 如果 m-lk<0 && n-rk<0,说明左右两边都缺衣服,需要 i 位置向左和向右传递|m-lk|+|n-rk|衣服,因为每轮只能给一个,所以需要|m-lk|+|n-rk|轮
- 如果 m-lk>0 && n-rk >0,说明左右两边都不缺衣服,都需要向 i 位置传递衣服,因为每轮只能给一个方向一个衣服,但接收方每轮可以接受2件衣服,所以 i 位置最多需要Math.max(||m-lk||,|n-rk|)轮就行了
- 如果 其中一方>0,另一方<0,比如一方需要30件衣服,一方需要输出25件衣服,那么同样最多需要Math.max(||m-lk||,|n-rk|)轮就行了
- 最后遍历每一个位置的洗衣机,求出每一个洗衣机需要的轮数,为了满足每个洗衣机条件,那么所有轮数中的最大值就是最后求得的移动最少的轮数,贪心策略:每一台机器都满足的情况下,取得的最小值
function process(arr) {
const sum = arr.reduce((item, next) => item + next, 0);
const len = arr.length;
const avg = sum % len;
if (avg !== 0) {
return Infinity;
}
// i 位置之前的累加和,不包括i位置
let leftSum = 0,
min = 0;
for (let i = 0; i < len; i++) {
let leftRest = leftSum - i * avg; // i 位置左边实际需要的
let rightRest = sum - leftSum - arr[i] - (size - i - 1) * avg; // i 位置右边实际需要的
if (leftRest < 0 && rightRest < 0) {
min = Math.max(min, Math.abs(leftRest) + Math.abs(rightRest));
} else {
min = Math.max(min, Math.max(Math.abs(leftRest), Math.abs(rightRest)));
}
leftSum += arr[i];
}
return min;
}