0517-超级洗衣机

Raphael Liu Lv10

假设有 n ** ** 台超级洗衣机放在同一排上。开始的时候,每台洗衣机内可能有一定量的衣服,也可能是空的。

在每一步操作中,你可以选择任意 m (1 <= m <= n) 台洗衣机,与此同时将每台洗衣机的一件衣服送到相邻的一台洗衣机。

给定一个整数数组 machines 代表从左至右每台洗衣机中的衣物数量,请给出能让所有洗衣机中剩下的衣物的数量相等的 最少的操作步数
。如果不能使每台洗衣机中衣物的数量相等,则返回 -1

示例 1:

**输入:** machines = [1,0,5]
**输出:** 3
**解释:**
第一步:    1     0 <-- 5    =>    1     1     4
第二步:    1 <-- 1 <-- 4    =>    2     1     3    
第三步:    2     1 <-- 3    =>    2     2     2   

示例 2:

**输入:** machines = [0,3,0]
**输出:** 2
**解释:**
第一步:    0 <-- 3     0    =>    1     2     0    
第二步:    1     2 --> 0    =>    1     1     1     

示例 3:

**输入:** machines = [0,2,0]
**输出:** -1
**解释:**
不可能让所有三个洗衣机同时剩下相同数量的衣物。

提示:

  • n == machines.length
  • 1 <= n <= 104
  • 0 <= machines[i] <= 105

方法一:贪心

设所有洗衣机内的衣服个数之和为 tot,要使最终所有洗衣机内的衣服个数相同,那么 tot 必须是 n 的倍数,否则我们直接返回 -1。

记 avg}=\dfrac{\textit{tot}}{n,定义 machines}[i]’=\textit{machines}[i]-\textit{avg,若 machines}[i]’ 为正则说明需要移出 machines}[i]’ 件衣服,为负则说明需要移入 -\textit{machines}[i]’ 件衣服。

将前 i 台洗衣机看成一组,记作 A,其余洗衣机看成另一组,记作 B。设 sum}[i]=\sum_{j=0}^i \textit{machines}[j]’,若 sum}[i] 为正则说明需要从 A 向 B 移入 sum}[i] 件衣服,为负则说明需要从 B 向 A 移入 -\textit{sum}[i] 件衣服。

我们分两种情况来考虑操作步数:

  1. A 与 B 两组之间的衣服,最多需要 \max_{i=0}^{n-1}|\textit{sum}[i]| 次衣服移动;
  2. 组内的某一台洗衣机内的衣服数量过多,需要向左右两侧移出衣服,这最多需要 \max_{i=0}^{n-1}\textit{machines}[i]’ 次衣服移动。

取两者的最大值即为答案。

[sol1-Python3]
1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution:
def findMinMoves(self, machines: List[int]) -> int:
tot = sum(machines)
n = len(machines)
if tot % n:
return -1
avg = tot // n
ans, s = 0, 0
for num in machines:
num -= avg
s += num
ans = max(ans, abs(s), num)
return ans
[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
int findMinMoves(vector<int> &machines) {
int tot = accumulate(machines.begin(), machines.end(), 0);
int n = machines.size();
if (tot % n) {
return -1;
}
int avg = tot / n;
int ans = 0, sum = 0;
for (int num: machines) {
num -= avg;
sum += num;
ans = max(ans, max(abs(sum), num));
}
return ans;
}
};
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int findMinMoves(int[] machines) {
int tot = Arrays.stream(machines).sum();
int n = machines.length;
if (tot % n != 0) {
return -1;
}
int avg = tot / n;
int ans = 0, sum = 0;
for (int num : machines) {
num -= avg;
sum += num;
ans = Math.max(ans, Math.max(Math.abs(sum), num));
}
return ans;
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Solution {
public int FindMinMoves(int[] machines) {
int tot = machines.Sum();
int n = machines.Length;
if (tot % n != 0) {
return -1;
}
int avg = tot / n;
int ans = 0, sum = 0;
foreach (int num in machines) {
int tmp = num - avg;
sum += tmp;
ans = Math.Max(ans, Math.Max(Math.Abs(sum), tmp));
}
return ans;
}
}
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
func findMinMoves(machines []int) (ans int) {
tot := 0
for _, v := range machines {
tot += v
}
n := len(machines)
if tot%n > 0 {
return -1
}
avg := tot / n
sum := 0
for _, num := range machines {
num -= avg
sum += num
ans = max(ans, max(abs(sum), num))
}
return
}

func abs(x int) int {
if x < 0 {
return -x
}
return x
}

func max(a, b int) int {
if b > a {
return b
}
return a
}
[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var findMinMoves = function(machines) {
const tot = eval(machines.join('+'));
const n = machines.length;
if (tot % n !== 0) {
return -1;
}
let avg = Math.floor(tot / n);
let ans = 0, sum = 0;
for (let num of machines) {
num -= avg;
sum += num;
ans = Math.max(ans, Math.max(Math.abs(sum), num));
}
return ans;
};

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组 machines 的长度。

  • 空间复杂度:O(1)。只需要常数的空间存放若干变量。

 Comments
On this page
0517-超级洗衣机