leetcode
leetcode 451 ~ 500
超级洗衣机

超级洗衣机

难度:

标签:

题目描述

假设有 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

代码结果

运行时间: 30 ms, 内存: 16.9 MB


/*
思路:
1. 首先计算所有洗衣机中衣物的总数,如果不能整除洗衣机的数量,则返回-1。
2. 计算每台洗衣机应有的平均衣物数。
3. 遍历洗衣机,计算每台洗衣机相对于平均数的累积差值,并记录最大绝对累积差值。
4. 返回最大绝对累积差值,即为最小的操作步数。
*/
import java.util.stream.IntStream;
 
public class SuperWashingMachines {
    public int findMinMoves(int[] machines) {
        int total = IntStream.of(machines).sum();
        int n = machines.length;
        if (total % n != 0) {
            return -1;
        }
        int avg = total / n;
        int[] diff = IntStream.of(machines).map(load -> load - avg).toArray();
        int currSum = 0;
        int maxMoves = IntStream.of(diff).map(diffLoad -> {
            currSum += diffLoad;
            return Math.abs(currSum);
        }).max().orElse(0);
        return maxMoves;
    }
}
 

解释

方法:

这个题解的思路是先计算出所有洗衣机中衣服的总数,如果总数不能被洗衣机数量整除,说明无法使每台洗衣机的衣服数量相等,直接返回-1。否则,计算出每台洗衣机最终应该有的衣服数量avg。然后遍历machines数组,用当前洗衣机的衣服数量减去avg,得到每台洗衣机还需要移入或移出的衣服数量。在遍历过程中,维护一个变量s表示前i台洗衣机累计还需要移入或移出的衣服数量,同时更新操作次数ans为max(ans, abs(s), num),即ans取ans、s的绝对值和当前洗衣机需要移动的衣服数量num三者的最大值。最终返回ans即可。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么题解中首先检查衣服总数是否能被洗衣机数量整除?这一步的逻辑依据是什么?
检查衣服总数是否能被洗衣机数量整除是为了确定是否存在一种可能的分配方式使得每台洗衣机最终都有相同数量的衣服。如果总数不能被整除,那么无论如何调整,都不可能达到每台洗衣机都有相等的衣服数量,因为衣服无法被均匀分配。这一步是检查问题是否有解的必要前提。
🦆
在题解的逻辑中,变量`s`表示前i台洗衣机累计还需要移入或移出的衣服数量。这个累积的衣服数量与最终的操作次数有什么关系?
变量`s`的绝对值代表了为了使前i台洗衣机达到平均衣服数量,需要进行的总的衣服移动次数。如果`s`的值较大(无论正负),说明累积的衣服移动量大,那么为了平衡这些洗衣机到达平均值,需要更多的操作。因此,`s`的绝对值是决定最终操作次数的一个重要因素。
🦆
题解中提到,更新操作次数`ans`为`max(ans, abs(s), num)`。请解释为什么需要同时考虑`s`的绝对值和当前洗衣机的`num`?
这种更新方式确保了操作次数`ans`足够覆盖所有单步和多步的衣服移动需求。`abs(s)`反映了到当前机器为止的累积移动需求,而`num`则显示了当前机器单独的移动需求。在某些情况下,累积需求可能不如某台具体机器的单次需求大,反之亦然。通过取这三者的最大值,可以确保无论是局部还是全局的衣服移动需求都能被满足,从而计算出确保所有洗衣机衣服数量平衡的最少操作次数。
🦆
如果在某次迭代中,`num`为正值,而累积的`s`也为正值,这种情况下如何理解这两个变量对操作次数的影响?
当`num`和`s`都为正值时,这表示当前洗衣机有多余的衣服,并且之前的洗衣机总体上也有多余的衣服。在这种情况下,`num`表示当前洗衣机独立需要移出的衣服数量,而`s`表示从开始到当前洗衣机为止,总共需要移出的衣服数量。这种情况下,实际操作次数会取决于这两者之中的较大值,因为它涵盖了解决局部和全局不平衡的最大需求。

相关问题