Minimum Swaps to Group All 1's Together II

Medium
5 days ago
<p>A <strong>swap</strong> is defined as taking two <strong>distinct</strong> positions in an array and swapping the values in them.</p> <p>A <strong>circular</strong> array is defined as an array where we consider the <strong>first</strong> element and the <strong>last</strong> element to be <strong>adjacent</strong>.</p> <p>Given a <strong>binary</strong> <strong>circular</strong> array <code>nums</code>, return <em>the minimum number of swaps required to group all </em><code>1</code><em>'s present in the array together at <strong>any location</strong></em>.</p> <p>&nbsp;</p> <p><strong class="example">Example 1:</strong></p> <pre> <strong>Input:</strong> nums = [0,1,0,1,1,0,0] <strong>Output:</strong> 1 <strong>Explanation:</strong> Here are a few of the ways to group all the 1's together: [0,<u>0</u>,<u>1</u>,1,1,0,0] using 1 swap. [0,1,<u>1</u>,1,<u>0</u>,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. </pre> <p><strong class="example">Example 2:</strong></p> <pre> <strong>Input:</strong> nums = [0,1,1,1,0,0,1,1,0] <strong>Output:</strong> 2 <strong>Explanation:</strong> 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. </pre> <p><strong class="example">Example 3:</strong></p> <pre> <strong>Input:</strong> nums = [1,1,0,0,1] <strong>Output:</strong> 0 <strong>Explanation:</strong> 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. </pre> <p>&nbsp;</p> <p><strong>Constraints:</strong></p> <ul> <li><code>1 &lt;= nums.length &lt;= 10<sup>5</sup></code></li> <li><code>nums[i]</code> is either <code>0</code> or <code>1</code>.</li> </ul>
Sample Answer

Naive Solution

The naive solution would involve iterating through all possible subarrays of length ones (the number of 1s in the array) and counting the number of 0s in each subarray. The minimum number of 0s would then be the answer, as each 0 would need to be swapped out. This approach would have a time complexity of O(n^2), where n is the length of the array, due to the nested loops required to iterate through all possible subarrays.

Optimal Solution

A more efficient solution can be achieved using a sliding window approach. First, count the total number of 1s in the array. This represents the size of our window. Then, iterate through the array using a sliding window of that size, counting the number of 0s within each window. The minimum number of 0s encountered is the answer.

Code (Python)

def min_swaps(nums):
    ones = sum(nums)
    n = len(nums)
    if ones == 0 or ones == n:
        return 0
    
    min_zeros = float('inf')
    
    for i in range(n):
        zeros = 0
        for j in range(ones):
            if nums[(i + j) % n] == 0:
                zeros += 1
        min_zeros = min(min_zeros, zeros)
        
    return min_zeros

# Example Usage
nums1 = [0,1,0,1,1,0,0]
print(f"Input: {nums1}, Output: {min_swaps(nums1)}") # Output: 1

nums2 = [0,1,1,1,0,0,1,1,0]
print(f"Input: {nums2}, Output: {min_swaps(nums2)}") # Output: 2

nums3 = [1,1,0,0,1]
print(f"Input: {nums3}, Output: {min_swaps(nums3)}") # Output: 0

Code (Java)

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

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

        int minZeros = Integer.MAX_VALUE;

        for (int i = 0; i < n; i++) {
            int zeros = 0;
            for (int j = 0; j < ones; j++) {
                if (nums[(i + j) % n] == 0) {
                    zeros++;
                }
            }
            minZeros = Math.min(minZeros, zeros);
        }

        return minZeros;
    }

    public static void main(String[] args) {
        Solution sol = new Solution();

        int[] nums1 = {0, 1, 0, 1, 1, 0, 0};
        System.out.println("Input: [0,1,0,1,1,0,0], Output: " + sol.minSwaps(nums1)); // Output: 1

        int[] nums2 = {0, 1, 1, 1, 0, 0, 1, 1, 0};
        System.out.println("Input: [0,1,1,1,0,0,1,1,0], Output: " + sol.minSwaps(nums2)); // Output: 2

        int[] nums3 = {1, 1, 0, 0, 1};
        System.out.println("Input: [1,1,0,0,1], Output: " + sol.minSwaps(nums3)); // Output: 0
    }
}

Big(O) Run-time Analysis

The optimal solution has a time complexity of O(n), where n is the length of the array. The outer loop iterates through the array once, and the inner loop iterates ones times (where ones is the number of 1s in the array). In the worst case, ones could be equal to n, making the inner loop also O(n). Thus the dominant factor is the outer loop, making the overall time complexity O(n).

Big(O) Space Usage Analysis

The space complexity of the optimal solution is O(1), constant space. We only use a few extra variables to store the count of ones and the minimum number of zeros, regardless of the input array size.

Edge Cases

  1. Empty array: If the input array is empty, the code should handle this gracefully. In the provided code, this case is implicitly handled because the loop will not execute, and the initial value of min_zeros (infinity) will be returned. However, it's good practice to explicitly check for this and return 0.
  2. Array with all 0s or all 1s: If the array contains only 0s or only 1s, no swaps are needed. The provided code handles this efficiently with the check if ones == 0 or ones == n: return 0.
  3. Large array: The code should handle very large arrays efficiently without causing memory issues or exceeding time limits. The O(n) time complexity and O(1) space complexity of the optimal solution make it suitable for large arrays.
  4. Negative numbers: The problem statement specifies that the array contains only 0s and 1s. If the array could potentially contain negative numbers, input validation would be needed to ensure that only binary values are processed.
  5. Circular array: The circular property is handled by using the modulo operator % when accessing array elements within the sliding window, ensuring that the window wraps around the array.