title: Bitwise XOR of All Pairings
slug: bitwise-xor-of-all-pairings
difficulty: medium
leetcode_id: 2425
leetcode_url: https://leetcode.com/problems/bitwise-xor-of-all-pairings/
categories:
  - arrays
  - math
patterns:
  - slug: greedy
    is_optimal: true

function_signature: "def xor_all_nums(nums1: list[int], nums2: list[int]) -> int:"

test_cases:
  visible:
    - input: { nums1: [2, 1, 3], nums2: [10, 2, 5, 0] }
      expected: 13
    - input: { nums1: [1, 2], nums2: [3, 4] }
      expected: 0
  hidden:
    - input: { nums1: [1], nums2: [1] }
      expected: 0
    - input: { nums1: [5], nums2: [3, 7] }
      expected: 0
    - input: { nums1: [1, 2, 3], nums2: [4] }
      expected: 4
    - input: { nums1: [0], nums2: [0, 0, 0] }
      expected: 0
    - input: { nums1: [1, 1], nums2: [2, 2] }
      expected: 0
    - input: { nums1: [7, 8, 9], nums2: [1, 2, 3] }
      expected: 0

description: |
  You are given two **0-indexed** arrays, `nums1` and `nums2`, consisting of non-negative integers.

  Let there be another array, `nums3`, which contains the bitwise XOR of **all pairings** of integers between `nums1` and `nums2` (every integer in `nums1` is paired with every integer in `nums2` **exactly once**).

  Return *the **bitwise XOR** of all integers in* `nums3`.

constraints: |
  - `1 <= nums1.length, nums2.length <= 10^5`
  - `0 <= nums1[i], nums2[j] <= 10^9`

examples:
  - input: "nums1 = [2,1,3], nums2 = [10,2,5,0]"
    output: "13"
    explanation: "A possible nums3 array is [8,0,7,2,11,3,4,1,9,1,6,3]. The bitwise XOR of all these numbers is 13."
  - input: "nums1 = [1,2], nums2 = [3,4]"
    output: "0"
    explanation: "All possible pairs of bitwise XORs are nums1[0] ^ nums2[0], nums1[0] ^ nums2[1], nums1[1] ^ nums2[0], and nums1[1] ^ nums2[1]. Thus, one possible nums3 array is [2,5,1,6]. 2 ^ 5 ^ 1 ^ 6 = 0, so we return 0."

explanation:
  intuition: |
    At first glance, this problem seems to require generating all `m * n` pairwise XORs (where `m = len(nums1)` and `n = len(nums2)`), then XORing them all together. With constraints up to `10^5` for both arrays, that's potentially `10^10` operations — far too slow.

    The key insight comes from a fundamental property of XOR: **a value XORed with itself cancels out** (`x ^ x = 0`). This means if any value appears an **even number of times** in the final XOR, it contributes nothing to the result.

    Think of it like this: imagine laying out all pairwise XORs in a grid. Each element `nums1[i]` appears in **exactly `n` pairs** (once with each element of `nums2`). Similarly, each element `nums2[j]` appears in **exactly `m` pairs**.

    When we XOR all pairs together, we're effectively XORing each `nums1[i]` a total of `n` times, and each `nums2[j]` a total of `m` times. If `n` is even, all `nums1` elements cancel out. If `m` is even, all `nums2` elements cancel out.

    This reduces the problem to simple parity checks on the array lengths.

  approach: |
    We solve this using **XOR properties and parity analysis**:

    **Step 1: Understand the contribution of each element**

    - Each element in `nums1` is XORed with every element in `nums2`, so it appears in `len(nums2)` pairs
    - Each element in `nums2` is XORed with every element in `nums1`, so it appears in `len(nums1)` pairs
    - When we XOR all pairs, each `nums1[i]` is XORed `len(nums2)` times total

    &nbsp;

    **Step 2: Apply the cancellation property**

    - If `len(nums2)` is even, each `nums1[i]` appears an even number of times and cancels out
    - If `len(nums2)` is odd, each `nums1[i]` appears an odd number of times and contributes once
    - The same logic applies to `nums2` elements based on `len(nums1)`

    &nbsp;

    **Step 3: Compute the result based on parity**

    - `result = 0`
    - If `len(nums2)` is odd: XOR all elements of `nums1` into result
    - If `len(nums1)` is odd: XOR all elements of `nums2` into result
    - Return the final result

    &nbsp;

    This elegant solution avoids generating any pairs at all, working in O(m + n) time.

  common_pitfalls:
    - title: The Brute Force Trap
      description: |
        The naive approach generates all `m * n` pairwise XORs:

        ```python
        for a in nums1:
            for b in nums2:
                result ^= (a ^ b)
        ```

        With `m, n <= 10^5`, this results in up to `10^10` operations — a guaranteed **Time Limit Exceeded**. The mathematical insight about parity is essential to solve this efficiently.
      wrong_approach: "Nested loops generating all pairs"
      correct_approach: "Use parity to determine which elements contribute"

    - title: Forgetting Both Arrays Can Contribute
      description: |
        It's easy to focus on just one array's contribution. Remember:

        - `nums1` contributes if `len(nums2)` is **odd**
        - `nums2` contributes if `len(nums1)` is **odd**

        Both conditions can be true simultaneously! For example, if both arrays have odd lengths, elements from **both** arrays contribute to the final XOR.
      wrong_approach: "Only checking one array's length parity"
      correct_approach: "Check both len(nums1) and len(nums2) independently"

    - title: Confusing Which Length Matters
      description: |
        A subtle error is checking the wrong length for each array:

        - `nums1` elements appear `len(nums2)` times (not `len(nums1)` times)
        - `nums2` elements appear `len(nums1)` times (not `len(nums2)` times)

        If you check `len(nums1) % 2` to decide whether to include `nums1`, you'll get the wrong answer. The **other** array's length determines the contribution.
      wrong_approach: "Checking len(nums1) % 2 for nums1's contribution"
      correct_approach: "Check len(nums2) % 2 for nums1's contribution"

  key_takeaways:
    - "**XOR cancellation**: `x ^ x = 0` — values appearing an even number of times cancel out entirely"
    - "**Parity analysis**: When elements repeat based on array lengths, check if the count is odd or even to determine contribution"
    - "**Avoid unnecessary computation**: Mathematical insight can reduce O(n^2) or worse problems to O(n)"
    - "**Bit manipulation patterns**: Many XOR problems have elegant solutions based on fundamental properties like `x ^ x = 0` and `x ^ 0 = x`"

  time_complexity: "O(m + n). We iterate through each array at most once, where `m = len(nums1)` and `n = len(nums2)`."
  space_complexity: "O(1). We only use a single variable to accumulate the XOR result."

solutions:
  - approach_name: Parity-Based XOR
    is_optimal: true
    code: |
      def xor_all_nums(nums1: list[int], nums2: list[int]) -> int:
          result = 0
          len1, len2 = len(nums1), len(nums2)

          # Each nums1 element appears len2 times in all pairs
          # If len2 is odd, it contributes to the final XOR
          if len2 % 2 == 1:
              for num in nums1:
                  result ^= num

          # Each nums2 element appears len1 times in all pairs
          # If len1 is odd, it contributes to the final XOR
          if len1 % 2 == 1:
              for num in nums2:
                  result ^= num

          return result
    explanation: |
      **Time Complexity:** O(m + n) — Single pass through each array at most once.

      **Space Complexity:** O(1) — Only one variable used.

      We leverage the XOR cancellation property: elements appearing an even number of times contribute nothing. Each element in `nums1` appears `len(nums2)` times, and vice versa. We only XOR elements whose appearance count is odd.

  - approach_name: Pythonic One-Liner
    is_optimal: true
    code: |
      from functools import reduce
      from operator import xor

      def xor_all_nums(nums1: list[int], nums2: list[int]) -> int:
          # XOR nums1 if len(nums2) is odd, XOR nums2 if len(nums1) is odd
          return (
              (reduce(xor, nums1, 0) if len(nums2) % 2 else 0) ^
              (reduce(xor, nums2, 0) if len(nums1) % 2 else 0)
          )
    explanation: |
      **Time Complexity:** O(m + n) — Same as the explicit version.

      **Space Complexity:** O(1) — Constant extra space.

      A more compact version using `reduce` to XOR all elements. The logic is identical: include `nums1`'s XOR if `len(nums2)` is odd, include `nums2`'s XOR if `len(nums1)` is odd.

  - approach_name: Brute Force
    is_optimal: false
    code: |
      def xor_all_nums(nums1: list[int], nums2: list[int]) -> int:
          result = 0

          # XOR every possible pair
          for a in nums1:
              for b in nums2:
                  result ^= (a ^ b)

          return result
    explanation: |
      **Time Complexity:** O(m * n) — Nested loops over both arrays.

      **Space Complexity:** O(1) — Only tracking result.

      This directly computes the XOR of all pairs. While correct, it's far too slow for large inputs (up to `10^10` operations). Included to illustrate why the mathematical insight is necessary. This will cause TLE on LeetCode.
