Leetcode 517. Super washing machine (greedy method + net output of piped water)

Posted by Farside on Wed, 29 Sep 2021 20:02:48 +0200

1. Title

Link: https://leetcode-cn.com/problems/super-washing-machines/

Let's say there are n super washing machines on the same row. At the beginning, each washing machine may have a certain amount of clothes or it may be empty.
In each step of operation, you can select any m (1 < = m < = n) washing machines, and send a piece of clothes from each washing machine to an adjacent washing machine at the same time.
Given an integer array machines representing the number of clothes in each washing machine from left to right, please give the minimum number of operation steps that can make the number of clothes left in all washing machines equal. If the number of clothes in each washing machine cannot be made equal, return - 1.

Example 1:
Input: machines = [1,0,5]
Output: 3
Explanation:
Step 1: 1 0 < -- 5 = > 1 1 4
Step 2: 1 < -- 1 < -- 4 = > 2 1 3
Step 3: 2 1 < -- 3 = > 2 2

Example 2:
Input: machines = [0,3,0]
Output: 2
Explanation:
Step 1: 0 < -- 3 0 = > 1 2 0
Step 2: 1 2 -- > 0 = > 1

Example 3:
Input: machines = [0,2,0]
Output: - 1
Explanation:
It is impossible for all three washing machines to leave the same amount of clothes at the same time.

Example 4: (I found it in the error case myself. Only by understanding this example can I understand the meaning of the question)
Input: machines = [4,0,0,4]
Output: 2
Explanation: why 2? Because m washing machines can be selected at a time
4 --> 0 0 <-- 4 => 3 1 1 3
3 --> 1 1 <-- 3 => 2 2 2 2

Example 5:
Input: machines = [5,4,3,2,1]
Output: 3

Example 6:
Input: machines = [4,2,11,3,3,1]
Output: 7

2. Problem solving

Method 1: greedy method

  • 1.1 basic ideas

  • 1.2 Code:

#Greedy 
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

Episode:

To be honest, after reading the official words and ideas at that time, I felt understood, but suddenly I thought, these examples, alas! Calculate the sum of (num - = AVG) > 0, that is, find the number of all excess clothes? The official examples 1, 2 and 3 are all satisfied. The following code is used:

class Solution:
    def findMinMoves(self, machines: List[int]) -> int:
        tot = sum(machines)
        n = len(machines)
        if tot % n:
            return -1
        avg = tot // n
        ans = 0
        for num in machines:
            num -= avg
            if num >0:
                ans += num
        return ans

Found wrong

Here is example 4. Multiple washing machines can be called at the same time, but each washing machine can only perform one of three operations:

  • Add clothes
  • Cut clothes
  • unchanged

Method 2: greedy method

  • The transmission of clothes is like the transmission of water through pipes. Each time, it can go from one to the next and then to another. A new concept appears: net input and net output
  • Find the maximum net output greater than 0 for all laundry, which is the number of times

Looking back at method 1, why ans = max(ans, abs(s), num), not the sum of (num - = AVG) > 0, why not sum, because the concern is that the * * maximum value of all washing machines is the required value, because the output operations of multiple washing machines can be carried out synchronously, and the sum is meaningless.

  • 2.1 code steps
    The net output of each washing machine to the left and right satisfies the relationship:
  • left[i] = -right[i-1]
  • right[i] = machines[i] - avg - left[i]

PS: if positive number is output, negative number is input; The output on the right is equal to the output required by itself plus the output on the left (that is, plus the input on the left)

The video is C + +. Write Python as follows:

#Method 2: maximum net output of pipeline transmission water
class Solution:
    def findMinMoves(self, machines: List[int]) -> int:
        tot = sum(machines)
        n = len(machines)
        if tot % n:
            return -1
        avg = tot // n
        
        left = [0] * n
        right = [0] * n
        left[0] = 0
        right[0] = machines[0] - avg
        left[n-1] = machines[n-1] - avg
        right[n-1] = 0
        for i in range(1,n-1):
            left[i] = -right[i-1]
            right[i] = machines[i] - avg - left[i]

        ans = 0
        for i in range(n):
            temp = 0
            if left[i] > 0:
                temp += left[i]
            if right[i] > 0:
                temp += right[i]  
            ans = max(ans,temp)
        return ans  

Reference article link:
1. Method 1: greed

Topics: Python Algorithm leetcode