From ddd739002bad536207eab6e06399a24595099af1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 24 Jul 2026 03:53:30 +0000 Subject: [PATCH] feat: add solution for 3514. Number of Unique XOR Triplets II --- .../analysis.md | 51 +++++++++++++++ .../problem.md | 64 +++++++++++++++++++ .../solution_daily_20260724.go | 51 +++++++++++++++ .../solution_daily_20260724_test.go | 61 ++++++++++++++++++ 4 files changed, 227 insertions(+) create mode 100644 problems/3514-number-of-unique-xor-triplets-ii/analysis.md create mode 100644 problems/3514-number-of-unique-xor-triplets-ii/problem.md create mode 100644 problems/3514-number-of-unique-xor-triplets-ii/solution_daily_20260724.go create mode 100644 problems/3514-number-of-unique-xor-triplets-ii/solution_daily_20260724_test.go diff --git a/problems/3514-number-of-unique-xor-triplets-ii/analysis.md b/problems/3514-number-of-unique-xor-triplets-ii/analysis.md new file mode 100644 index 0000000..a933bfd --- /dev/null +++ b/problems/3514-number-of-unique-xor-triplets-ii/analysis.md @@ -0,0 +1,51 @@ +# 3514. Number of Unique XOR Triplets II + +[LeetCode Link](https://leetcode.com/problems/number-of-unique-xor-triplets-ii/) + +Difficulty: Medium +Topics: Array, Math, Bit Manipulation, Enumeration +Acceptance Rate: 40.2% + +## Hints + +### Hint 1 + +The brute-force idea is to iterate over every triplet `(i, j, k)` with `i <= j <= k`, XOR the three values, and drop the results into a set. With `n` up to 1500 that is on the order of `n^3 / 6 ≈ 5 * 10^8` operations — too slow. Before optimizing, ask yourself: what is special about the *values* here, and does the ordering `i <= j <= k` actually restrict which XOR results are reachable? + +### Hint 2 + +Because indices may repeat (`i <= j <= k` allows `i == j == k`), the ordering constraint adds nothing: you can reach every value `a ^ b ^ c` where `a`, `b`, `c` are chosen from the array with repetition. XOR is commutative and associative, so only the *set of distinct values* matters, not positions or counts. Reduce `nums` to its distinct values first. + +### Hint 3 + +Every `nums[i]` is at most 1500, so any XOR of these values stays below 2048 (11 bits). That means the number of *reachable* XOR values is tiny — bounded by 2048 — no matter how large `n` is. Split the work in two stages: first compute the set of all pairwise XORs `P = { x ^ y }`, then XOR that set against the distinct values once more to get all triplet XORs. Each stage is bounded by `|distinct| * 2048`, which is comfortably fast. + +## Approach + +Let `D` be the set of distinct values in `nums`. + +1. **Reduce to distinct values.** Duplicates never create a new XOR result, so collapse `nums` to `D`. Since `1 <= nums[i] <= 1500`, `|D| <= 1500`. + +2. **Build the pairwise-XOR set `P`.** For every ordered pair `(x, y)` with `x, y in D`, record `x ^ y`. This automatically includes `0` (from `x ^ x`) and every single value `x` is representable later. Because each value is under 2048, `P` lives in a boolean array of size 2048. This costs `O(|D|^2)` time. + +3. **Build the triplet-XOR set `T`.** For every `p in P` and every `d in D`, record `p ^ d`. This yields every `x ^ y ^ z` for `x, y, z in D`, which is exactly the set of reachable triplet values. This costs `O(|P| * |D|) = O(2048 * |D|)`. + +4. **Count** the number of `true` entries in `T`. + +Why the two-stage split works: a triplet XOR is `(x ^ y) ^ z`. Stage 2 collects all pairwise results into `P`, and stage 3 combines each of them with a third distinct value. Because we already store `0 in P`, values reachable with "fewer distinct picks" are also covered — e.g. `p = 0` gives back the single elements `d`, and `p = x ^ y` with `z` reproducing one of them gives back a single value too. + +**Walkthrough on `nums = [1, 3]`:** `D = {1, 3}`. Pairwise XORs: `1^1 = 0`, `1^3 = 2`, `3^3 = 0`, so `P = {0, 2}`. Triplet XORs: `0^1 = 1`, `0^3 = 3`, `2^1 = 3`, `2^3 = 1`, so `T = {1, 3}`. Count is `2`. ✅ + +## Complexity Analysis + +Let `V = 2048` be the value bound (next power of two above the max XOR) and `d = |D| <= 1500`. + +Time Complexity: `O(d^2 + V * d)` — the pairwise stage dominates at roughly `d^2` (about `2.25 * 10^6`), and the triplet stage is `V * d`. Both are well within limits. +Space Complexity: `O(V + d)` — two boolean arrays of size `V` for `P` and `T`, plus the distinct-value list. + +## Edge Cases + +- **Single element (`n == 1`):** the only triplet is `a ^ a ^ a = a`, so the answer is `1`. The distinct set is `{a}`, `P = {0}`, and `T = {a}` — handled naturally. +- **All identical elements:** collapses to a single distinct value, same as the `n == 1` case; answer is `1`. +- **Two elements:** `P = {0, a^b}` and `T = {a, b}`, giving `2` distinct triplet values (matches Example 1). Confirms the ordering constraint imposes no real restriction. +- **Values that XOR to `0`:** `0` is always reachable via `a ^ a ^ a`... but note `0` only appears in `T` if some `d` cancels a `p`; for a single distinct value the smallest result is `a` itself, so make sure the sizing (2048) covers the largest possible XOR, not just the largest input. diff --git a/problems/3514-number-of-unique-xor-triplets-ii/problem.md b/problems/3514-number-of-unique-xor-triplets-ii/problem.md new file mode 100644 index 0000000..ef7dbfa --- /dev/null +++ b/problems/3514-number-of-unique-xor-triplets-ii/problem.md @@ -0,0 +1,64 @@ +--- +number: "3514" +frontend_id: "3514" +title: "Number of Unique XOR Triplets II" +slug: "number-of-unique-xor-triplets-ii" +difficulty: "Medium" +topics: + - "Array" + - "Math" + - "Bit Manipulation" + - "Enumeration" +acceptance_rate: 4023.6 +is_premium: false +created_at: "2026-07-24T03:51:53.056616+00:00" +fetched_at: "2026-07-24T03:51:53.056616+00:00" +link: "https://leetcode.com/problems/number-of-unique-xor-triplets-ii/" +date: "2026-07-24" +--- + +# 3514. Number of Unique XOR Triplets II + +You are given an integer array `nums`. + +A **XOR triplet** is defined as the XOR of three elements `nums[i] XOR nums[j] XOR nums[k]` where `i <= j <= k`. + +Return the number of **unique** XOR triplet values from all possible triplets `(i, j, k)`. + + + +**Example 1:** + +**Input:** nums = [1,3] + +**Output:** 2 + +**Explanation:** + +The possible XOR triplet values are: + + * `(0, 0, 0) -> 1 XOR 1 XOR 1 = 1` + * `(0, 0, 1) -> 1 XOR 1 XOR 3 = 3` + * `(0, 1, 1) -> 1 XOR 3 XOR 3 = 1` + * `(1, 1, 1) -> 3 XOR 3 XOR 3 = 3` + + + +The unique XOR values are `{1, 3}`. Thus, the output is 2. + +**Example 2:** + +**Input:** nums = [6,7,8,9] + +**Output:** 4 + +**Explanation:** + +The possible XOR triplet values are `{6, 7, 8, 9}`. Thus, the output is 4. + + + +**Constraints:** + + * `1 <= nums.length <= 1500` + * `1 <= nums[i] <= 1500` diff --git a/problems/3514-number-of-unique-xor-triplets-ii/solution_daily_20260724.go b/problems/3514-number-of-unique-xor-triplets-ii/solution_daily_20260724.go new file mode 100644 index 0000000..0947dfc --- /dev/null +++ b/problems/3514-number-of-unique-xor-triplets-ii/solution_daily_20260724.go @@ -0,0 +1,51 @@ +package main + +// Number of Unique XOR Triplets II +// +// Approach: Because i <= j <= k permits repeated indices and XOR is +// commutative/associative, the reachable triplet values are exactly +// { x ^ y ^ z : x, y, z in distinct(nums) }. Every value is <= 1500, so any +// XOR stays below 2048 (11 bits). We first compute the set of pairwise XORs P, +// then XOR P against the distinct values to obtain every triplet XOR, using +// fixed-size boolean arrays as bitsets. +func uniqueXorTriplets(nums []int) int { + const limit = 2048 // next power of two above the max XOR of values <= 1500 + + // Collect distinct values. + seen := make([]bool, limit) + distinct := make([]int, 0, len(nums)) + for _, v := range nums { + if !seen[v] { + seen[v] = true + distinct = append(distinct, v) + } + } + + // Stage 1: all pairwise XORs (includes 0 from x ^ x). + pair := make([]bool, limit) + for i := 0; i < len(distinct); i++ { + for j := i; j < len(distinct); j++ { + pair[distinct[i]^distinct[j]] = true + } + } + + // Stage 2: XOR each pairwise result with each distinct value -> triplet XORs. + triplet := make([]bool, limit) + for p := 0; p < limit; p++ { + if !pair[p] { + continue + } + for _, d := range distinct { + triplet[p^d] = true + } + } + + // Count reachable triplet values. + count := 0 + for _, ok := range triplet { + if ok { + count++ + } + } + return count +} diff --git a/problems/3514-number-of-unique-xor-triplets-ii/solution_daily_20260724_test.go b/problems/3514-number-of-unique-xor-triplets-ii/solution_daily_20260724_test.go new file mode 100644 index 0000000..eedc4f3 --- /dev/null +++ b/problems/3514-number-of-unique-xor-triplets-ii/solution_daily_20260724_test.go @@ -0,0 +1,61 @@ +package main + +import "testing" + +func TestUniqueXorTriplets(t *testing.T) { + tests := []struct { + name string + nums []int + expected int + }{ + {"example 1: two elements {1,3} -> {1,3}", []int{1, 3}, 2}, + {"example 2: {6,7,8,9} -> {6,7,8,9}", []int{6, 7, 8, 9}, 4}, + {"edge case: single element yields only itself", []int{5}, 1}, + {"edge case: all identical collapses to one value", []int{7, 7, 7, 7}, 1}, + {"edge case: duplicates do not add new values", []int{1, 1, 3, 3}, 2}, + {"edge case: value 1 alone", []int{1}, 1}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := uniqueXorTriplets(tt.nums) + if got != tt.expected { + t.Errorf("uniqueXorTriplets(%v) = %d, want %d", tt.nums, got, tt.expected) + } + }) + } +} + +// TestUniqueXorTripletsBruteForce cross-checks the optimized solution against a +// straightforward O(n^3) reference on small random-ish inputs. +func TestUniqueXorTripletsBruteForce(t *testing.T) { + inputs := [][]int{ + {1, 3}, + {6, 7, 8, 9}, + {5}, + {2, 4, 6, 8, 10}, + {1, 2, 3, 4, 5, 6}, + {1500, 1, 1499, 2}, + } + + brute := func(nums []int) int { + set := map[int]struct{}{} + n := len(nums) + for i := 0; i < n; i++ { + for j := i; j < n; j++ { + for k := j; k < n; k++ { + set[nums[i]^nums[j]^nums[k]] = struct{}{} + } + } + } + return len(set) + } + + for _, in := range inputs { + want := brute(in) + got := uniqueXorTriplets(in) + if got != want { + t.Errorf("uniqueXorTriplets(%v) = %d, brute force = %d", in, got, want) + } + } +}