超级洗衣机问题

超级洗衣机问题

作者:Grey

原文地址:

博客园:超级洗衣机问题

CSDN:超级洗衣机问题

题目链接:LeetCode 517. 超级洗衣机问题

主要思路

有两个显而易见的结论:

假设所有衣服的数量之和是sum,如果sum % N != 0,则无论如何都无法做到让所有洗衣机平分衣服。

假设洗衣机的数量是size,那么每个洗衣机需要分担avg = sum / size这么多件衣服。

假设我们在i位置,i左侧有i-1个位置,这i个位置上应该要有i*avg件衣服,假设现在i位置之前的累加和是leftSum, 用

leftRest = leftSum - i * avg

得到的结果就是i左侧还差多少件衣服(如果是负数,就是富余多少件衣服)。

同理,i右侧有size - i - 1个位置,这size - i - 1 个位置理论上应该有avg * (size - i - 1)件衣服。用

rightRest = sum - leftSum - avg*(size - i - 1)

得到的结果就是i右侧还差多少件衣服(如果是负数,就是富余多少件衣服)。

如果

leftRest < 0 && rightRest < 0

说明i位置两侧都不够衣服,要让i位置同时给左侧和右侧都贡献衣服,因为可以不可同时贡献,所以i贡献的衣服是

Math.abs(leftRest) + Math.abs(rightRest)

举例说明:

[3,6,3]这个数组,对于中间位置的6来说,要向左侧贡献1件衣服,要向右侧贡献1件衣服。

除了这种情况,要么左侧衣服多了,要不右侧衣服多了,要不两侧衣服都多了,这个时候,需要两侧向i位置贡献一部分衣服,因为左右两侧可以同时向i位置贡献,所以贡献的衣服数量取决于是两侧多的数量,即:

Math.max(Math.abs(leftRest),Math.abs(rightRest))

举例说明:

[5,1,6]这个数组,对于中间位置的1来说,左侧需要给它贡献1件衣服,右侧需要给它贡献2件衣服,而且根据题目条件,这种情况是可以同时贡献衣服的,所以只需要两轮即可。

自此,所有情况讨论完毕,完整代码如下:

public static int findMinMoves(int[] arr) {
        if (null == arr || 0 == arr.length) {
            return 0;
        }
        int sum = 0;
        int size = arr.length;
        for (int item : arr) {
            sum += item;
        }
        if (sum % size != 0) {
            return -1;
        }
        int avg = sum / size;
        int leftSum = 0;
        int ans = 0;
        for (int i = 0; i < size; i++) {
            // 左侧还差多少
            int leftRest = leftSum - i * avg;
            // 右侧还差多少
            int rightRest = (sum - leftSum - arr[i]) - (size - i - 1) * avg;
            if (leftRest < 0 && rightRest < 0) {
                // 左侧右侧都差一些才到平均值
                // 此时就需要中间位置向左边和右边都丢一些衣服
                ans = Math.max(ans, Math.abs(leftRest) + Math.abs(rightRest));
            } else {
                // 左侧多,右侧少,多的通过中间丢一些到左侧
                // 右侧少,左侧多,多的通过中间丢一些到右侧
                // 左右侧都多,则可以**同时**向中间丢衣服
                ans = Math.max(ans, Math.max(Math.abs(leftRest), Math.abs(rightRest)));
            }
            leftSum += arr[i];
        }
        return ans;
    }

更多内容见:算法和数据结构笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

GreyZeng

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

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

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

打赏作者

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

抵扣说明:

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

余额充值