题意
一共 n n n台洗衣机,每台洗衣机有 a [ i ] a[i] a[i]台衣服,每次可以选择 m m m台洗衣机向相邻的洗衣机传递一件衣服,问让所有洗衣机都有相同的衣服数量需要至少多少次操作?
题解
感觉这个题目还是比较难想的,还是看了别人的博客的才会做的
-
首先判断不可能的情况
-
我们考虑任意一台洗衣机i(从0开始计算),考虑为了让最后全部洗衣机都有相同的衣服,需要通过i传递的衣服有多少,我们计算在i左边的衣服总数前缀和prefixSum和右边的衣服总数后缀和suffixSum
假设最终结果每台洗衣机有avg件衣服,计算
{ l e f t = p r e f i x S u m − a v g ∗ i r i g h t = s u f f i x S u m − a v g ∗ ( l e n − i − 1 ) \begin{cases} left = prefixSum - avg*i \\ right = suffixSum - avg*(len - i - 1) \end{cases} {left=prefixSum−avg∗iright=suffixSum−avg∗(len−i−1)如果l e f t eft eft为负数,表示需要通过 i i i(包括从 i i i)传递 l e f t left left件衣服过来,如果 l e f t left left为正数,表示需要通过传递 l e f t left left件衣服到右边(包括第 i i i个位置). r i g h t right right同理
分以下三种情况讨论- 如果 l e f t left left和 r i g h t right right都大于0,表示两边都多衣服,因为可以同时操作,因为通过i传递的衣服为 m a x ( l e f t , r i g h t ) max(left, right) max(left,right)
- 如果 l e f t left left和 r i g h t right right都小于0,表示两边都少衣服,但是因此每次i只能传递一件衣服,因此答案为 a b s ( l e f t + r i g h t ) abs(left+right) abs(left+right)
- 其余的情况是一个大于0一个小于0,其实和第一种类似,为
m
a
x
(
a
b
s
(
l
e
f
t
)
,
a
b
s
(
r
i
g
h
t
)
)
max(abs(left), abs(right))
max(abs(left),abs(right))
以上的方法我们可以计算出了为了到达最终状态,每个位置需要通过的衣服数,最后的答案应该是所有的数字中取最大值。
代码
public int findMinMoves(int[] machines) {
int sum = 0;
int len = machines.length;
for (int i = 0; i < len; i++) sum += machines[i];
if (sum % len != 0) return -1;
int avg = sum / len;
int prefixSum = 0;
int result = 0;
for (int i = 0; i < machines.length; i++) {
int suffixSum = sum - prefixSum - machines[i];
int left = prefixSum - avg * i;
int right = suffixSum - avg * (len - i - 1);
if (left >= 0 && right >= 0) result = Math.max(result, Math.max(left, right));
else if (left < 0 && right < 0) result = Math.max(result, -(left + right));
else result = Math.max(result, Math.max(result, Math.max(Math.abs(left), Math.abs(right))));
prefixSum += machines[i];
}
return result;
}