LeetCode517.超级洗衣机C++题解用最简单的思路写困难题

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/super-washing-machines
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

### 解题思路
左侧第一个数会出现以下几种情况:
1.需要右方提供数值;
2.需要给右方数值;
3.不需要动;
后面除了倒数第一个数会有以下情况:
1.被左侧拿数值,减去数值后小于或等于平均数值不需要多余处理,如果多则需要步骤叠加处理;
2.被左侧给数值,加上数值,无论怎样都不用特殊操作,因为只往右边传递数值,不会出现步骤叠加。

关键问题在于需要给左右都提供数值的数字,如果出现多个如何平衡的问题。
一步一步循序渐进,哪里有问题调试哪里,总会成功的uu们。
可以用{0,0,10,0,0,0,10,0,0,0},{0,3,0},{0,0,11,5},{11,0,0,5},{0,4,12,0}几个例子帮助理解。

### 代码

```cpp
class Solution {
public:
    int findMinMoves(vector<int>& machines) {
        // 首先不用多说了先算平均值和看是否合法(开胃菜)
        int sum = 0, ret = 0;
        for (auto m : machines) {
            sum += m;
        }
        int average = sum / machines.size();
        if (sum % machines.size() != 0) {
            return -1;
        }
        // 从头到尾遍历一遍,使所有值都变为平均值并记录操作数
        for (int i = 0; i < machines.size()-1; ++i) {
            // 用来记录当前操作所需要的最大步数为了给最大值服务的
            // 如果最大值需要给左右两个方向都提供数字,则需要叠加
            // now用来解决如果有多个最大值的所出现的问题
            int now = -1;
            // kkk用来表示当前数值与平均数的差值
            int kkk = abs(average - machines[i]);
            // 如果不等于就处理,等于直接跳过
            if (kkk > 0 ) {
                // 差值是a则至少需要a步
                if (kkk > ret) {
                    ret = kkk;
                }
                // 下面是平衡操作使所有数值都变为平均值
                // 如果大于平均值则当前值减去差值,后面的值加上差值
                // 因为从头开始不用考虑当前值前面的所有值
                if (machines[i] > average) {
                    machines[i] -= kkk;
                    machines[i+1] += kkk;
                }
                // 如果当前值小于平均值,则当前值加上差值,后面的值减去差值
                else {
                    machines[i] += kkk;
                    machines[i+1] -= kkk;
                    // 如果后面的值减去差值后还大于平均值,则还需要给右边的数数值
                    // 由于一次只能给一个数值,所以这里需要叠加次数
                    // 这块有点难理解,可以自己画一个例子辅助理解
                    // 本质上是找到最大的值然后计算所需要的最小操作数
                    if (machines[i + 1] > average) {
                        // uuu为后1数与平局数的差值
                        int uuu = machines[i + 1] - average;
                        // 由于步数不需要累加,就是说每一步操作之与上一步操作有关,
                        // 因为可以同时移动,now就等于当前所需要操作步数
                        now = kkk + uuu;
                        // 如果当前也就是后面这个数所需要的操作步数大于之前的,替换
                        if (now > ret) {
                            ret = now;
                        }
                    }
                }
            }
        }
        return ret;
        }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奇树谦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值