Minimum Swaps To Group All 1'S Together

Question

Given a binary array data, return the minimum number of swaps required to group all 1’s present in the array together in any place in the array.

Example 1:

Input: data = [1,0,1,0,1]
Output: 1

Explanation: There are 3 ways to group all 1's together:
[1,1,1,0,0] using 1 swap.
[0,1,1,1,0] using 2 swaps.
[0,0,1,1,1] using 1 swap.
The minimum is 1.

Example 2:

Input: data = [0,0,0,1,0]
Output: 0

Explanation: Since there is only one 1 in the array, no swaps are needed.
Example 3:

Example 3::

Input: data = [1,0,1,0,1,0,0,1,1,0,1]
Output: 3
Explanation: One possible solution that uses 3 swaps is [0,0,0,0,0,1,1,1,1,1,1].

Constraints:

  • 1 <= data.length <= 105
  • data[i] is either 0 or 1.

Solution

Intuition

To group all the 1s together, we can make a group of all number of 1s.

So for example if we have this array with 3 1's:

[1,0,0,0,0,0,0,...,1,0,1]

The longest group that we can make is 3. Which is the number of 1.

So if we can define a window of number of 1, we can then count the number of 0 inside that window to replace to 1

Next, we can keep sliding that windows and update number of 0 to swap

That's it:
$$ \text{number of swaps} = \text{number of 0 to replace in the window}$$

Implementation

class App:
    def numSwap(self, nums: List[int]) -> int:
        numberFrequency = Counter(nums)
        if numberFrequency[1] == 1: return 0
        
        left, right = 0, 0
        
        windowFrequency = {1: 0, 0: 0}
        
        # Initialise window range
        while (right < numberFrequency[1]):
            windowFrequency[nums[right]] += 1
            right += 1
            
		# After this loop here, `right` will be at 1 index ahead
        minSwap = windowFrequency[0]
        
        while (right < len(nums)):
            windowFrequency[nums[left]] -= 1
			# Therefore we move `left` first to match with right
            left += 1
            # And we don't have to move `right` bc it's already at the current index
            windowFrequency[nums[right]] += 1
            
            minSwap = min(minSwap, windowFrequency[0])
            right += 1
        
        return minSwap
        

Time complexity: $O(n)$ — $n$ is the number of element in the array
Space complexity: $O(n)$ — for the numberFrequency