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:
1 in data.1 (if they are already grouped).Input: data = [1,0,1,0,1] Output: 1
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.
Let's break down the optimized solution step by step:
1s are in the array. Let's call this totalOnes.totalOnes and slide it across the array.1s are in it. The number of 0s in the window is window size - number of 1's in window.1s found in any window of size totalOnes.totalOnes - maxOnesInWindow.0s in the best window to 1s.1s without redundant computation.
Let's walk through the example data = [1,0,1,0,1]:
totalOnes = 3).totalOnes - maxOnesInWindow = 3 - 2 = 1Brute-force Approach:
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;
};
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.