Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1151. Minimum Swaps to Group All 1's Together - Leetcode Solution

Problem Description

Given a binary array data (that is, an array consisting only of 0s and 1s), your task is to find the minimum number of swaps needed to group all the 1s together in the array.

Each swap can swap any two elements (not necessarily adjacent). The goal is to make all the 1s appear in a consecutive block, and you want to do this using as few swaps as possible.

Constraints:

  • There is always at least one 1 in data.
  • You may not need to move every 1 (if they are already grouped).
  • There is only one valid answer for each input.
Example:
Input: data = [1,0,1,0,1]
Output: 1

Thought Process

At first glance, it may seem like you need to try all possible swaps between 1s and 0s to group the 1s together. However, this brute-force approach would be inefficient, especially for large arrays.

Instead, notice that the minimum number of swaps is determined by how many 0s are present in the "window" (subarray) where you want to group all the 1s. Since you know the total number of 1s in the array, you can try to find a subarray of that length that contains the maximum number of 1s. The fewer 0s in that window, the fewer swaps you need to make.

This observation leads us to consider a sliding window approach, where you slide a window of size equal to the total number of 1s across the array and count the number of 0s in each window. The minimum number of 0s in any such window is the answer.

Solution Approach

Let's break down the optimized solution step by step:

  1. Count Total 1's:
    • First, count how many 1s are in the array. Let's call this totalOnes.
  2. Sliding Window:
    • Use a window of size totalOnes and slide it across the array.
    • For each window, count how many 1s are in it. The number of 0s in the window is window size - number of 1's in window.
  3. Track the Maximum 1's in Any Window:
    • Keep track of the maximum number of 1s found in any window of size totalOnes.
  4. Calculate the Minimum Swaps:
    • The minimum swaps needed is totalOnes - maxOnesInWindow.
    • This is because you only need to swap the 0s in the best window to 1s.
Why a Sliding Window?
  • Sliding window allows us to efficiently check all possible groupings of 1s without redundant computation.
  • It reduces the time complexity from quadratic to linear.

Example Walkthrough

Let's walk through the example data = [1,0,1,0,1]:

  1. Count Total 1's:
    • There are 3 ones in the array (totalOnes = 3).
  2. Sliding Window of Size 3:
    • First window: [1,0,1] → 2 ones
    • Second window: [0,1,0] → 1 one
    • Third window: [1,0,1] → 2 ones
  3. Find Maximum 1's in Any Window:
    • Maximum number of ones in any window is 2.
  4. Calculate Minimum Swaps:
    • totalOnes - maxOnesInWindow = 3 - 2 = 1
    • So, you need at least 1 swap to group all the ones together.
Why? Because the best you can do is get a window of 3 elements that contains 2 ones and 1 zero; swapping that zero with a one elsewhere groups all the ones.

Time and Space Complexity

Brute-force Approach:

  • Would involve checking all possible groupings and swap counts, which could be O(N2) or worse, where N is the array length.
Optimized Sliding Window Approach:
  • Counting total ones: O(N)
  • Sliding window: O(N) (each element is processed at most twice)
  • Total time complexity: O(N)
  • Space complexity: O(1) (only a few integer variables are used)
This makes the solution efficient and suitable for large input sizes.

Code Implementation

class Solution:
    def minSwaps(self, data):
        total_ones = sum(data)
        if total_ones == 0 or total_ones == len(data):
            return 0
        max_ones = curr_ones = sum(data[:total_ones])
        for i in range(total_ones, len(data)):
            curr_ones += data[i] - data[i - total_ones]
            max_ones = max(max_ones, curr_ones)
        return total_ones - max_ones
      
class Solution {
public:
    int minSwaps(vector<int>& data) {
        int totalOnes = 0;
        for (int num : data) totalOnes += num;
        if (totalOnes == 0 || totalOnes == data.size()) return 0;
        int currOnes = 0, maxOnes = 0;
        for (int i = 0; i < totalOnes; ++i) currOnes += data[i];
        maxOnes = currOnes;
        for (int i = totalOnes; i < data.size(); ++i) {
            currOnes += data[i] - data[i - totalOnes];
            maxOnes = max(maxOnes, currOnes);
        }
        return totalOnes - maxOnes;
    }
};
      
class Solution {
    public int minSwaps(int[] data) {
        int totalOnes = 0;
        for (int num : data) totalOnes += num;
        if (totalOnes == 0 || totalOnes == data.length) return 0;
        int currOnes = 0;
        for (int i = 0; i < totalOnes; i++) currOnes += data[i];
        int maxOnes = currOnes;
        for (int i = totalOnes; i < data.length; i++) {
            currOnes += data[i] - data[i - totalOnes];
            maxOnes = Math.max(maxOnes, currOnes);
        }
        return totalOnes - maxOnes;
    }
}
      
var minSwaps = function(data) {
    let totalOnes = data.reduce((a, b) => a + b, 0);
    if (totalOnes === 0 || totalOnes === data.length) return 0;
    let currOnes = 0;
    for (let i = 0; i < totalOnes; i++) currOnes += data[i];
    let maxOnes = currOnes;
    for (let i = totalOnes; i < data.length; i++) {
        currOnes += data[i] - data[i - totalOnes];
        maxOnes = Math.max(maxOnes, currOnes);
    }
    return totalOnes - maxOnes;
};
      

Summary

To solve the "Minimum Swaps to Group All 1's Together" problem, we recognized that the core challenge is to find a window where the 1s can be grouped with the least effort. By using a sliding window of size equal to the total number of 1s and counting the number of 0s in each window, we efficiently determine the minimum swaps needed. This approach is both elegant and efficient, reducing the problem from a potentially slow brute-force solution to a linear-time algorithm.