2 minute read

Problem Statement

problem-1863

Intuition

As I looked at the problem, I immediately thought of using a backtracking approach to generate all possible subsets of the given array. Then, I can calculate the XOR sum of each subset and sum them up to get the final result.

Approach

My approach involves defining a recursive function to generate all subsets using backtracking. Starting from an empty subset, I iterate through the array and at each step, I include the current element in the subset and recursively explore the remaining elements. After exploring all possibilities, I calculate the XOR sum of each subset and accumulate the results.

Complexity

  • Time complexity: The time complexity of this approach is O(2^N * N), where N is the number of elements in the input array. This is because there are 2^N subsets to generate, and for each subset, we need to calculate the XOR sum which takes O(N) time.
  • Space complexity: The space complexity is also O(2^N * N) because we need to store all generated subsets, each of which can have a maximum size of N.

Code


class Solution:
    def subsetXORSum(self, nums: List[int]) -> int:
        if not nums:
            return 0
        subsets = []
        N = len(nums)
        def backtrack(i, curr):
            subsets.append(curr[:])
            if i == N:
                return

            for j in range(i, N):
                curr.append(nums[j])
                backtrack(j + 1, curr)
                curr.pop()

        backtrack(0, [])
        res = 0
        for subset in subsets:
            curr = 0
            for num in subset:
                curr ^= num
            res += curr
        return res

Editorial Solution

Approach 1: Generate All Subsets Using Backtracking

class Solution:
    def subsetXORSum(self, nums):

        def generate_subsets(nums, index, subset, subsets):
            # Base case: index reached end of nums
            # Add the current subset to subsets
            if index == len(nums):
                subsets.append(subset[:])
                return

            # Generate subsets with nums[i]
            subset.append(nums[index])
            generate_subsets(nums, index + 1, subset, subsets)
            subset.pop()

            # Generate subsets without nums[i]
            generate_subsets(nums, index + 1, subset, subsets)

        # Generate all of the subsets
        subsets = []
        generate_subsets(nums, 0, [], subsets)

        # Compute the XOR total for each subset and add to the result
        result = 0
        for subset in subsets:
            subset_XOR_total = 0
            for num in subset:
                subset_XOR_total ^= num
            result += subset_XOR_total

        return result

Approach 2: Optimized Backtracking

class Solution:
    def subsetXORSum(self, nums: List[int]) -> int:

        def generate_subsets( nums: List[int], index: int, current_XOR: int) -> int:
            # Return current_XOR when all elements in nums are already considered
            if index == len(nums): return current_XOR

            # Calculate sum of subset xor with current element
            with_element = generate_subsets(nums, index + 1, current_XOR ^ nums[index])

            # Calculate sum of subset xor without current element
            without_element = generate_subsets(nums, index + 1, current_XOR)

            # Return sum of xor totals
            return with_element + without_element

        return generate_subsets(nums, 0, 0)