We use cookies (including Google cookies) to personalize ads and analyze traffic. By continuing to use our site, you accept our Privacy Policy.

Make the XOR of All Segments Equal to Zero

Number: 1913

Difficulty: Hard

Paid? No

Companies: Media.net


Problem Description

Given an array nums and an integer k, you need to determine the minimum number of elements to change in the array such that for every contiguous segment (subarray) of length k, the XOR of its elements is zero.


Key Insights

  • Because every segment of size k takes exactly one element from each of the k groups (based on index modulo k), the problem can be broken down by grouping indices with the same remainder when divided by k.
  • For each group, maintain a frequency map of the values that appear.
  • Use dynamic programming (DP) where the state represents the cumulative XOR achieved from processed groups.
  • For each group, consider either keeping some of its elements (thus leveraging their frequency counts) or changing all its elements (which contributes 0 to the count of unchanged elements).
  • The final answer is derived by subtracting the maximum number of unchanged elements that lead to a cumulative XOR of 0 from the total number of elements.

Space and Time Complexity

Time Complexity: O(n * (maximum XOR value)) – practically O(n * 1024) since possible XOR values range from 0 to 1023. Space Complexity: O(1024) for the DP array, plus O(n) for grouping elements.


Solution

We start by grouping the array elements based on their index modulo k. Each group represents the positions that contribute the same role in each k-length segment. For each group, we create a frequency map of numbers.

Then, we use DP where dp[x] indicates the maximum number of unchanged elements (from processed groups) that achieve a cumulative XOR equal to x. We initialize dp[0] = 0 and the rest as a very small number (negative infinity) because they are initially unreachable.

For every group:

  1. Create a temporary new DP array.
  2. For each possible XOR state and each unique number in the current group, update the new DP state at (current XOR XOR value) with the count of unchanged elements if this number is kept.
  3. Also consider the option of changing all numbers in the group (i.e., not preserving any count from the group), which means you carry forward the current DP state without improvement.

After processing all groups, dp[0] contains the maximum number of elements that did not change while achieving the desired cumulative XOR of 0. The minimum changes required is the total number of elements minus dp[0].


Code Solutions

def minChanges(nums, k):
    # Import Counter to get frequency counts
    from collections import Counter
    n = len(nums)
    
    # Group numbers based on index modulo k.
    groups = []
    for i in range(k):
        group = []
        for j in range(i, n, k):
            group.append(nums[j])
        groups.append(group)
    
    # Initialize DP array where dp[x] is the maximum number of unchanged elements 
    # with cumulative XOR x from the groups processed so far. There are 1024 possible states (0 to 1023).
    dp = [-10**9] * 1024
    dp[0] = 0  # Starting with cumulative XOR 0 and 0 unchanged elements
    
    # Process each group
    for group in groups:
        cnt = Counter(group)
        # new_dp will store the results after processing this current group.
        new_dp = [-10**9] * 1024
        
        # Option 1: Change all elements in this group so none are kept
        maxGroupSize = len(group)
        for x in range(1024):
            # When we change all the elements in this group, the XOR remains unchanged but we don't gain any kept element.
            # (This account for the possibility of assigning any value arbitrarily.)
            new_dp[x] = max(new_dp[x], dp[x])
        
        # Option 2: Keep some elements and use their frequency count
        for x in range(1024):
            if dp[x] < 0:
                continue
            # For each unique number in this group, consider keeping it.
            for num, frequency in cnt.items():
                new_xor = x ^ num
                # Increase unchanged count by frequency (we keep all occurrences of this number unchanged)
                new_dp[new_xor] = max(new_dp[new_xor], dp[x] + frequency)
                
        dp = new_dp  # Update dp to new_dp for the next group
    
    # Maximum number of unchanged elements for cumulative XOR 0
    maxUnchanged = dp[0]
    return n - maxUnchanged

# Example usage:
print(minChanges([1,2,0,3,0], 1))         # Expected output: 3
print(minChanges([3,4,5,2,1,7,3,4,7], 3))   # Expected output: 3
print(minChanges([1,2,4,1,2,5,1,2,6], 3))   # Expected output: 3
← Back to All Questions