算法作业22

题目地址https://leetcode.com/problems/super-washing-machines/#/description

题目描述:You have n super washing machines on a line. Initially, each washing machine has some dresses or is empty.

For each move, you could choose any m (1 ≤ m ≤ n) washing machines, and pass one dress of each washing machine to one of its adjacent washing machines at the same time .

Given an integer array representing the number of dresses in each washing machine from left to right on the line, you should find the minimum number of moves to make all the washing machines have the same number of dresses. If it is not possible to do it, return -1.

我的代码

class Solution {
public:
    int findMinMoves(vector<int>& machines) {
        int n=machines.size();
        vector<int> sums;
        int sum=0;
        for(int i=0;i<n;i++){
            sum+=machines[i];
            sums.push_back(sum);
        }
        if(sum%n!=0) return -1;
        int num=0,av = sum/n;
        for(int i=0;i<n;i++) sums[i]-=(av * (i+1));
        for(int i=0;i<n-1;i++){
            if(sums[i+1]-sums[i]>num)num=sums[i+1] - sums[i];
            if(0-sums[i]>num) num = 0-sums[i];
            if(sums[i] > num) num = sums[i];
        }
        return num;
    }
};

解题思路
用n来表示machines个数,sum来表示dresses的总和,显然,当n整除sum时,可以均分,否则不可以(返回-1)。
然后用sums[i]来表示前面i+1个machine里面dresses与目标额的差,即前面i+1个machines总共还需要从右边获取或者送出多少dresses。
对于第i个位置sums[i]而言,当其大于0,他需要向右送出k次,而当sums[i-1] < 0 时,他需要向左边的machine送-sums[i-1]次。即一个机器向右送出的次数取决于自己,向左送出的次数取决于左边的机器。由此,我们可以求出一个机器总的送出次数,取最大值即为最大操作数num。
复杂度为O(n)。
上面的步骤已经足够详细了,但还不足以证明结果的正确性。因此补充证明如下:
引理:在任何情况下,送出次数最大的所有点一定都是dresses数量非0的。
设ai是送出次数最大的点之一,如果sums[ai]<=0,那么其送出次数显然是-sums[ai-1],如果ai的dresses数量为0,那么显然sums[ai] = sums[ai-1] - av(av是最终的dresses平均值),显然有ai+1的送出数大于ai,矛盾。
如果sums[ai]>0,当ai的dresses = 0,显然有sums[ai-1] = sums[ai] +av;即ai-1的送出次数比ai大,矛盾。

由引理知,所有送出次数最大的点都是dresses非0的,因此每次可以对所有的dresses最大的点进行操作,显然,操作后,最大发送次数减小了1,由此可知,以上算法结果正确。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值