diff --git a/problems/3867-sum-of-gcd-of-formed-pairs/analysis.md b/problems/3867-sum-of-gcd-of-formed-pairs/analysis.md new file mode 100644 index 0000000..fa20010 --- /dev/null +++ b/problems/3867-sum-of-gcd-of-formed-pairs/analysis.md @@ -0,0 +1,93 @@ +# 3867. Sum of GCD of Formed Pairs + +[LeetCode Link](https://leetcode.com/problems/sum-of-gcd-of-formed-pairs/) + +Difficulty: Medium +Topics: Array, Math, Two Pointers, Sorting, Simulation, Number Theory +Acceptance Rate: 69.6% + +## Hints + +### Hint 1 + +The problem reads like a chain of separate steps: build one array, sort it, pair +things up, then reduce. Don't try to be clever about merging the steps — this is a +simulation problem. Handle each stage faithfully and the pieces fall into place. The +only questions are: how do I build `prefixGcd` efficiently, and how do I pair the +sorted elements without an expensive nested loop? + +### Hint 2 + +For `prefixGcd`, notice that `mxi` is just a running (prefix) maximum. You can compute +the whole array in one pass while carrying the max seen so far. For the pairing step, +"smallest unpaired with largest unpaired" after sorting is the textbook signal for the +**two-pointers** technique: one pointer at the front, one at the back, walking inward. + +### Hint 3 + +Once `prefixGcd` is sorted, set `left = 0` and `right = n - 1`. While `left < right`, +add `gcd(prefixGcd[left], prefixGcd[right])` to the answer, then move `left++` and +`right--`. The loop condition `left < right` handles the odd-length case for free: the +single middle element is exactly where the two pointers meet, so it is never paired and +never counted. No special-casing required. + +## Approach + +The task is a direct simulation with two efficiency-sensitive stages. + +**Stage 1 — Build `prefixGcd`.** For each index `i`, `mxi` is the maximum of +`nums[0..i]`, which is a prefix maximum. Keep a variable `mx` that we update to +`max(mx, nums[i])` as we scan left to right, and set +`prefixGcd[i] = gcd(nums[i], mx)`. This is a single `O(n)` pass (each `gcd` is +`O(log V)`), avoiding any `O(n^2)` recomputation of the max. + +For example, with `nums = [3, 6, 2, 8]`: + +- `i=0`: `mx=3`, `gcd(3,3)=3` +- `i=1`: `mx=6`, `gcd(6,6)=6` +- `i=2`: `mx=6`, `gcd(2,6)=2` +- `i=3`: `mx=8`, `gcd(8,8)=8` + +So `prefixGcd = [3, 6, 2, 8]`. + +**Stage 2 — Sort.** Sort `prefixGcd` in non-decreasing order: `[2, 3, 6, 8]`. + +**Stage 3 — Pair with two pointers.** The rule "pair the smallest unpaired with the +largest unpaired, repeatedly" is exactly a two-pointer sweep from both ends of the +sorted array. Start `left = 0`, `right = n - 1`: + +- `left=0, right=3`: `gcd(2, 8) = 2` +- `left=1, right=2`: `gcd(3, 6) = 3` +- `left=2, right=1`: `left < right` fails, stop. + +Sum `= 2 + 3 = 5`, matching the expected output. + +When `n` is odd, the two pointers eventually satisfy `left == right` on the middle +element, and the `left < right` guard stops the loop before it is used — so the middle +element is naturally ignored, as the problem requires. + +Computing `gcd` uses the Euclidean algorithm. Since values can be up to `10^9`, the sum +of GCDs across up to ~`5 * 10^4` pairs can exceed a 32-bit range in the worst case +(each GCD up to `10^9`), so accumulate the answer in a 64-bit integer to be safe. + +## Complexity Analysis + +Time Complexity: O(n log n) — the sort dominates; building `prefixGcd` is `O(n log V)` +and the two-pointer pass is `O(n log V)`, where `V` is the maximum value. +Space Complexity: O(n) — for the `prefixGcd` array (or O(1) auxiliary beyond it, +ignoring the sort's internal usage). + +## Edge Cases + +- **Single element (`n == 1`):** `prefixGcd` has one element; no pair can be formed and + the answer is `0`. The two-pointer loop never executes since `left < right` is false + immediately. +- **Odd length:** The middle element after sorting must be skipped. The `left < right` + condition handles this automatically — no explicit middle-index arithmetic needed. +- **All equal values:** e.g. `[5, 5, 5, 5]` gives `prefixGcd = [5, 5, 5, 5]`, and each + pair contributes `gcd(5, 5) = 5`. A good sanity check that pairing/summing works. +- **Large values (up to `10^9`) and many pairs:** Accumulate the sum in a 64-bit + integer to avoid overflow, since the total can exceed the 32-bit range. +- **Strictly increasing input:** `mxi == nums[i]` at every index, so + `prefixGcd[i] = gcd(nums[i], nums[i]) = nums[i]`; a useful case to confirm the prefix + max is tracked correctly. diff --git a/problems/3867-sum-of-gcd-of-formed-pairs/problem.md b/problems/3867-sum-of-gcd-of-formed-pairs/problem.md new file mode 100644 index 0000000..0805f9d --- /dev/null +++ b/problems/3867-sum-of-gcd-of-formed-pairs/problem.md @@ -0,0 +1,95 @@ +--- +number: "3867" +frontend_id: "3867" +title: "Sum of GCD of Formed Pairs" +slug: "sum-of-gcd-of-formed-pairs" +difficulty: "Medium" +topics: + - "Array" + - "Math" + - "Two Pointers" + - "Sorting" + - "Simulation" + - "Number Theory" +acceptance_rate: 6958.0 +is_premium: false +created_at: "2026-07-16T03:45:53.859780+00:00" +fetched_at: "2026-07-16T03:45:53.859780+00:00" +link: "https://leetcode.com/problems/sum-of-gcd-of-formed-pairs/" +date: "2026-07-16" +--- + +# 3867. Sum of GCD of Formed Pairs + +You are given an integer array `nums` of length `n`. + +Construct an array `prefixGcd` where for each index `i`: + + * Let `mxi = max(nums[0], nums[1], ..., nums[i])`. + * `prefixGcd[i] = gcd(nums[i], mxi)`. + + + +After constructing `prefixGcd`: + + * Sort `prefixGcd` in **non-decreasing** order. + * Form pairs by taking the **smallest unpaired** element and the **largest unpaired** element. + * Repeat this process until no more pairs can be formed. + * For each formed pair, **compute** the `gcd` of the two elements. + * If `n` is odd, the **middle** element in the `prefixGcd` array remains **unpaired** and should be ignored. + + + +Return an integer denoting the **sum of the GCD** values of all formed pairs. + +The term `gcd(a, b)` denotes the **greatest common divisor** of `a` and `b`. + + + +**Example 1:** + +**Input:** nums = [2,6,4] + +**Output:** 2 + +**Explanation:** + +Construct `prefixGcd`: + +`i` | `nums[i]` | `mxi` | `prefixGcd[i]` +---|---|---|--- +0 | 2 | 2 | 2 +1 | 6 | 6 | 6 +2 | 4 | 6 | 2 + +`prefixGcd = [2, 6, 2]`. After sorting, it forms `[2, 2, 6]`. + +Pair the smallest and largest elements: `gcd(2, 6) = 2`. The remaining middle element 2 is ignored. Thus, the sum is 2. + +**Example 2:** + +**Input:** nums = [3,6,2,8] + +**Output:** 5 + +**Explanation:** + +Construct `prefixGcd`: + +`i` | `nums[i]` | `mxi` | `prefixGcd[i]` +---|---|---|--- +0 | 3 | 3 | 3 +1 | 6 | 6 | 6 +2 | 2 | 6 | 2 +3 | 8 | 8 | 8 + +`prefixGcd = [3, 6, 2, 8]`. After sorting, it forms `[2, 3, 6, 8]`. + +Form pairs: `gcd(2, 8) = 2` and `gcd(3, 6) = 3`. Thus, the sum is `2 + 3 = 5`. + + + +**Constraints:** + + * `1 <= n == nums.length <= 105` + * `1 <= nums[i] <= 10​​​​​​​9` diff --git a/problems/3867-sum-of-gcd-of-formed-pairs/solution_daily_20260716.go b/problems/3867-sum-of-gcd-of-formed-pairs/solution_daily_20260716.go new file mode 100644 index 0000000..0fb2205 --- /dev/null +++ b/problems/3867-sum-of-gcd-of-formed-pairs/solution_daily_20260716.go @@ -0,0 +1,48 @@ +package main + +import "sort" + +// Approach: Simulate the three stages directly. +// 1. Build prefixGcd in one pass using a running prefix maximum: +// prefixGcd[i] = gcd(nums[i], max(nums[0..i])). +// 2. Sort prefixGcd in non-decreasing order. +// 3. Pair the smallest unpaired with the largest unpaired using two pointers +// (left at the front, right at the back) and sum gcd(left, right) for each +// pair. The `left < right` guard leaves the middle element unpaired when n +// is odd, exactly as required. +// +// The answer is accumulated in an int64 to avoid overflow, since values can be +// up to 1e9 across many pairs. + +// gcd returns the greatest common divisor of a and b using the Euclidean +// algorithm. Assumes non-negative inputs (constraints guarantee nums[i] >= 1). +func gcd(a, b int) int { + for b != 0 { + a, b = b, a%b + } + return a +} + +func sumGcd(nums []int) int64 { + n := len(nums) + + // Stage 1: build prefixGcd with a running maximum. + prefixGcd := make([]int, n) + mx := 0 + for i, v := range nums { + if v > mx { + mx = v + } + prefixGcd[i] = gcd(v, mx) + } + + // Stage 2: sort in non-decreasing order. + sort.Ints(prefixGcd) + + // Stage 3: two-pointer pairing from both ends. + var sum int64 + for left, right := 0, n-1; left < right; left, right = left+1, right-1 { + sum += int64(gcd(prefixGcd[left], prefixGcd[right])) + } + return sum +} diff --git a/problems/3867-sum-of-gcd-of-formed-pairs/solution_daily_20260716_test.go b/problems/3867-sum-of-gcd-of-formed-pairs/solution_daily_20260716_test.go new file mode 100644 index 0000000..41461a9 --- /dev/null +++ b/problems/3867-sum-of-gcd-of-formed-pairs/solution_daily_20260716_test.go @@ -0,0 +1,56 @@ +package main + +import "testing" + +func TestSumGcd(t *testing.T) { + tests := []struct { + name string + nums []int + expected int64 + }{ + { + name: "example 1: [2,6,4] -> sorted [2,2,6], gcd(2,6)=2", + nums: []int{2, 6, 4}, + expected: 2, + }, + { + name: "example 2: [3,6,2,8] -> sorted [2,3,6,8], gcd(2,8)+gcd(3,6)=5", + nums: []int{3, 6, 2, 8}, + expected: 5, + }, + { + name: "edge case: single element has no pairs", + nums: []int{7}, + expected: 0, + }, + { + name: "edge case: two identical elements, gcd(5,5)=5", + nums: []int{5, 5}, + expected: 5, + }, + { + name: "edge case: odd length middle ignored", + nums: []int{5, 5, 5, 5, 5}, + expected: 10, // sorted [5,5,5,5,5]: gcd(5,5)+gcd(5,5)=10, middle skipped + }, + { + name: "edge case: strictly increasing keeps values as prefixGcd", + nums: []int{1, 2, 3, 4}, + expected: 2, // prefixGcd [1,2,3,4]: gcd(1,4)+gcd(2,3)=1+1=2 + }, + { + name: "edge case: large values, no overflow", + nums: []int{1000000000, 1000000000}, + expected: 1000000000, // gcd(1e9,1e9)=1e9 + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := sumGcd(tt.nums) + if result != tt.expected { + t.Errorf("sumGcd(%v) = %d, want %d", tt.nums, result, tt.expected) + } + }) + } +}