Minimum Swaps to Group All 1's Together II

MEDIUM

Description

A swap is defined as taking two distinct positions in an array and swapping the values in them.

A circular array is defined as an array where we consider the first element and the last element to be adjacent.

Given a binary circular array nums, return the minimum number of swaps required to group all 1's present in the array together at any location.

 

Example 1:

Input: nums = [0,1,0,1,1,0,0]
Output: 1
Explanation: Here are a few of the ways to group all the 1's together:
[0,0,1,1,1,0,0] using 1 swap.
[0,1,1,1,0,0,0] using 1 swap.
[1,1,0,0,0,0,1] using 2 swaps (using the circular property of the array).
There is no way to group all 1's together with 0 swaps.
Thus, the minimum number of swaps required is 1.

Example 2:

Input: nums = [0,1,1,1,0,0,1,1,0]
Output: 2
Explanation: Here are a few of the ways to group all the 1's together:
[1,1,1,0,0,0,0,1,1] using 2 swaps (using the circular property of the array).
[1,1,1,1,1,0,0,0,0] using 2 swaps.
There is no way to group all 1's together with 0 or 1 swaps.
Thus, the minimum number of swaps required is 2.

Example 3:

Input: nums = [1,1,0,0,1]
Output: 0
Explanation: All the 1's are already grouped together due to the circular property of the array.
Thus, the minimum number of swaps required is 0.

 

Constraints:

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

Approaches

Checkout 3 different approaches to solve Minimum Swaps to Group All 1's Together II. Click on different approaches to view the approach and algorithm in detail.

Space-Optimized Sliding Window with Modulo Arithmetic

This is the most optimal approach. It builds upon the sliding window idea but avoids the O(N) space complexity of creating a doubled array. The circularity of the array is handled elegantly and efficiently by using the modulo operator (%) for calculating indices that would otherwise wrap around.

Algorithm

  • Calculate totalOnes, the total count of 1s in nums.
  • If totalOnes is 0 or n, return 0.
  • Calculate the number of 1s in the first window of size totalOnes (indices 0 to totalOnes - 1). Let this be currentOnes.
  • Initialize maxOnes = currentOnes.
  • Iterate i from 1 to n - 1. This i represents the starting index of the sliding window.
  • The element leaving the window is at index i - 1.
  • The element entering the window is at index i + totalOnes - 1. To handle the wrap-around, we calculate the actual index as (i + totalOnes - 1) % n.
  • Update currentOnes in O(1) by subtracting nums[i - 1] and adding nums[(i + totalOnes - 1) % n].
  • Update maxOnes = max(maxOnes, currentOnes).
  • After iterating through all n possible starting positions, return totalOnes - maxOnes.

This approach refines the sliding window technique to achieve optimal space complexity. Instead of physically creating a doubled array, we simulate the behavior of a circular window on the original array.

  1. As before, we first count totalOnes to determine the window size.
  2. We compute the number of 1s in the initial window, which spans from index 0 to totalOnes - 1. This gives us our initial currentOnes and maxOnes.
  3. We then slide the window n-1 more times to cover all possible circular starting positions. The loop for the window's start index i runs from 1 to n-1.
  4. In each iteration, we update currentOnes. The element leaving the window is at index i - 1. The element entering the window would be at index i + totalOnes - 1 in a linear array. To handle the circularity, we find its actual index using the modulo operator: (i + totalOnes - 1) % n.
  5. The update rule is: currentOnes = currentOnes - nums[i - 1] + nums[(i + totalOnes - 1) % n].
  6. We keep track of the maximum currentOnes seen in maxOnes.
  7. Finally, the minimum number of swaps is totalOnes - maxOnes, which represents the minimum number of 0s in any possible window.

This method provides the same linear time efficiency as the doubled array approach but with the significant advantage of constant space usage.

class Solution {
    public int minSwaps(int[] nums) {
        int n = nums.length;
        int totalOnes = 0;
        for (int x : nums) {
            totalOnes += x;
        }

        if (totalOnes == 0 || totalOnes == n) {
            return 0;
        }

        int currentOnes = 0;
        // Calculate ones in the first window (from 0 to totalOnes-1)
        for (int i = 0; i < totalOnes; i++) {
            currentOnes += nums[i];
        }

        int maxOnes = currentOnes;
        // Slide the window and handle wrap-around with modulo
        for (int i = 1; i < n; i++) {
            // Element leaving is at i-1
            int leavingElement = nums[i - 1];
            // Element entering is at (i + totalOnes - 1) % n
            int enteringElement = nums[(i + totalOnes - 1) % n];
            
            currentOnes = currentOnes - leavingElement + enteringElement;
            maxOnes = Math.max(maxOnes, currentOnes);
        }

        return totalOnes - maxOnes;
    }
}

Complexity Analysis

Time Complexity: O(N), where N is the length of the array. We perform a few passes over the array, each taking linear time.Space Complexity: O(1), as we only use a few variables to store counts and indices, making it very memory-efficient.

Pros and Cons

Pros:
  • Optimal time complexity of O(N).
  • Optimal space complexity of O(1).
  • It's the most efficient solution for this problem.
Cons:
  • The use of modulo arithmetic for indexing can be slightly less intuitive than the doubled array approach for some developers.

Code Solutions

Checking out 5 solutions in different languages for Minimum Swaps to Group All 1's Together II. Click on different languages to view the code.

public class Solution {
    public int MinSwaps(int[] nums) {
        int k = nums.Sum();
        int n = nums.Length;
        int cnt = 0;
        for (int i = 0; i < k; ++i) {
            cnt += nums[i];
        }
        int mx = cnt;
        for (int i = k; i < n + k; ++i) {
            cnt += nums[i % n] - nums[(i - k + n) % n];
            mx = Math.Max(mx, cnt);
        }
        return k - mx;
    }
}

Video Solution

Watch the video walkthrough for Minimum Swaps to Group All 1's Together II



Patterns:

Sliding Window

Data Structures:

Array

Subscribe to Scale Engineer newsletter

Learn about System Design, Software Engineering, and interview experiences every week.

No spam, unsubscribe at any time.