From c158da44417f9ca57cc9b317e9decc687101a453 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 14 Jun 2026 05:15:42 +0000 Subject: [PATCH] feat: add solution for 2130. Maximum Twin Sum of a Linked List --- .../analysis.md | 54 +++++++++++++ .../problem.md | 76 +++++++++++++++++++ .../solution.go | 47 ++++++++++++ .../solution_test.go | 41 ++++++++++ 4 files changed, 218 insertions(+) create mode 100644 problems/2130-maximum-twin-sum-of-a-linked-list/analysis.md create mode 100644 problems/2130-maximum-twin-sum-of-a-linked-list/problem.md create mode 100644 problems/2130-maximum-twin-sum-of-a-linked-list/solution.go create mode 100644 problems/2130-maximum-twin-sum-of-a-linked-list/solution_test.go diff --git a/problems/2130-maximum-twin-sum-of-a-linked-list/analysis.md b/problems/2130-maximum-twin-sum-of-a-linked-list/analysis.md new file mode 100644 index 0000000..73a8fc0 --- /dev/null +++ b/problems/2130-maximum-twin-sum-of-a-linked-list/analysis.md @@ -0,0 +1,54 @@ +# 2130. Maximum Twin Sum of a Linked List + +[LeetCode Link](https://leetcode.com/problems/maximum-twin-sum-of-a-linked-list/) + +Difficulty: Medium +Topics: Linked List, Two Pointers, Stack +Acceptance Rate: 82.1% + +## Hints + +### Hint 1 + +A "twin" pairs node `i` with node `n-1-i`. That means you're pairing the front of the list with the back, the second element with the second-to-last, and so on — working inward from both ends. Whenever a problem asks you to pair the start with the end of a sequence, think about how you'd reach both ends at once. With an array that's trivial (`a[i] + a[n-1-i]`), but a singly linked list only lets you walk forward. How can you bridge that gap? + +### Hint 2 + +There are two broad ways to get random/back-to-front access on a singly linked list. One is to dump the values into a structure that *does* support indexing or last-in-first-out access — an array or a **stack**. The other is to physically rearrange the list so the second half points backward. Either way, the goal is to line up node `i` with node `n-1-i` and add them. Try the simplest version first: copy all values into a slice, then use two indices marching toward the middle. + +### Hint 3 + +The optimal trick avoids the extra storage: use the classic **slow/fast pointer** to find the middle in one pass, then **reverse the second half** in place. Now you have two list halves — the original first half (head ... mid) and the reversed second half (tail ... mid). Walk both simultaneously, one node at a time; each step gives you exactly one twin pair. Take the running maximum of the sums. This is O(n) time and O(1) extra space, since reversal just rewires the existing nodes. + +## Approach + +The relationship "node `i` is the twin of node `n-1-i`" is the same pairing you'd get by folding the list in half. So the whole problem reduces to: pair up the first half with the reversed second half and find the largest pair sum. + +**Optimal approach — middle + reverse + two pointers (O(1) space):** + +1. **Find the middle** with the slow/fast pointer technique. Start both at `head`; advance `slow` by one and `fast` by two until `fast` runs off the end. Because the length is even, when `fast == nil`, `slow` sits at the start of the second half (node `n/2`). + +2. **Reverse the second half** in place starting from `slow`. Standard iterative reversal with three pointers (`prev`, `curr`, `next`). After this, `prev` is the head of the reversed second half — i.e., the original last node. + +3. **Walk both halves together.** Let `first = head` and `second = prev`. At each step, `first.Val + second.Val` is one twin sum: on the first step it's node `0` + node `n-1`, then node `1` + node `n-2`, and so on. Keep a running maximum. Advance both pointers; stop when the reversed half is exhausted (`second == nil`). + +Walking through Example 1, `head = [5,4,2,1]`: +- Middle search lands `slow` on the node with value `2` (index 2). +- Reversing `[2,1]` gives `[1,2]`, headed by the node with value `1`. +- Pair up: `5 + 1 = 6`, then `4 + 2 = 6`. Maximum is `6`. ✓ + +**Simpler alternative — stack or array (O(n) space):** Push every value onto a slice in order, then use two indices `lo = 0`, `hi = n-1` moving inward, summing `vals[lo] + vals[hi]`. Easier to write and reason about; the only cost is the extra O(n) storage. Great as a first pass before optimizing. + +This problem is a clean, very approachable Medium — the 82% acceptance rate reflects that. If the in-place reversal feels fiddly, start with the array version to get a green check, then come back and tighten the space. Both are completely valid. + +## Complexity Analysis + +Time Complexity: O(n) — one pass to find the middle, one pass to reverse the second half, one pass to compare pairs. All linear. +Space Complexity: O(1) for the optimal reverse-in-place approach (only a handful of pointers). The array/stack alternative is O(n). + +## Edge Cases + +- **Minimum size (n = 2):** The smallest legal list, e.g. `[1, 100000]`. There's exactly one twin pair, so the answer is just the sum of the two nodes. Verify the slow/fast loop and reversal don't mishandle a two-node list (they shouldn't — `slow` ends on the second node, and reversing a single-node tail is a no-op). +- **All equal values:** e.g. `[5,5,5,5]`. Every twin sum is identical; make sure the max logic still returns that value rather than, say, only comparing the first pair. +- **Maximum value pairs not adjacent:** The largest twin sum may come from any pair, not necessarily the outermost. Don't short-circuit after the first pair — always scan all `n/2` pairs. +- **Guaranteed even length:** The constraints promise an even number of nodes (≥ 2), so you don't need to handle odd lengths or an empty list. Relying on this keeps the middle-finding logic simple. diff --git a/problems/2130-maximum-twin-sum-of-a-linked-list/problem.md b/problems/2130-maximum-twin-sum-of-a-linked-list/problem.md new file mode 100644 index 0000000..1929b72 --- /dev/null +++ b/problems/2130-maximum-twin-sum-of-a-linked-list/problem.md @@ -0,0 +1,76 @@ +--- +number: "2130" +frontend_id: "2130" +title: "Maximum Twin Sum of a Linked List" +slug: "maximum-twin-sum-of-a-linked-list" +difficulty: "Medium" +topics: + - "Linked List" + - "Two Pointers" + - "Stack" +acceptance_rate: 8207.3 +is_premium: false +created_at: "2026-06-14T05:14:24.340404+00:00" +fetched_at: "2026-06-14T05:14:24.340404+00:00" +link: "https://leetcode.com/problems/maximum-twin-sum-of-a-linked-list/" +date: "2026-06-14" +--- + +# 2130. Maximum Twin Sum of a Linked List + +In a linked list of size `n`, where `n` is **even** , the `ith` node (**0-indexed**) of the linked list is known as the **twin** of the `(n-1-i)th` node, if `0 <= i <= (n / 2) - 1`. + + * For example, if `n = 4`, then node `0` is the twin of node `3`, and node `1` is the twin of node `2`. These are the only nodes with twins for `n = 4`. + + + +The **twin sum** is defined as the sum of a node and its twin. + +Given the `head` of a linked list with even length, return _the**maximum twin sum** of the linked list_. + + + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2021/12/03/eg1drawio.png) + + + **Input:** head = [5,4,2,1] + **Output:** 6 + **Explanation:** + Nodes 0 and 1 are the twins of nodes 3 and 2, respectively. All have twin sum = 6. + There are no other nodes with twins in the linked list. + Thus, the maximum twin sum of the linked list is 6. + + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2021/12/03/eg2drawio.png) + + + **Input:** head = [4,2,2,3] + **Output:** 7 + **Explanation:** + The nodes with twins present in this linked list are: + - Node 0 is the twin of node 3 having a twin sum of 4 + 3 = 7. + - Node 1 is the twin of node 2 having a twin sum of 2 + 2 = 4. + Thus, the maximum twin sum of the linked list is max(7, 4) = 7. + + +**Example 3:** + +![](https://assets.leetcode.com/uploads/2021/12/03/eg3drawio.png) + + + **Input:** head = [1,100000] + **Output:** 100001 + **Explanation:** + There is only one node with a twin in the linked list having twin sum of 1 + 100000 = 100001. + + + + +**Constraints:** + + * The number of nodes in the list is an **even** integer in the range `[2, 105]`. + * `1 <= Node.val <= 105` diff --git a/problems/2130-maximum-twin-sum-of-a-linked-list/solution.go b/problems/2130-maximum-twin-sum-of-a-linked-list/solution.go new file mode 100644 index 0000000..3b65a02 --- /dev/null +++ b/problems/2130-maximum-twin-sum-of-a-linked-list/solution.go @@ -0,0 +1,47 @@ +package main + +// Maximum Twin Sum of a Linked List +// +// Approach: find the middle of the list with slow/fast pointers, reverse the +// second half in place, then walk both halves in lockstep. Each step pairs +// node i with node n-1-i (its twin); track the maximum pair sum. +// Time: O(n), Space: O(1). + +// ListNode is a node in a singly linked list. +type ListNode struct { + Val int + Next *ListNode +} + +func pairSum(head *ListNode) int { + // Step 1: find the start of the second half (index n/2). + // For an even-length list, when fast reaches nil, slow is at node n/2. + slow, fast := head, head + for fast != nil && fast.Next != nil { + slow = slow.Next + fast = fast.Next.Next + } + + // Step 2: reverse the second half starting at slow. + var prev *ListNode + curr := slow + for curr != nil { + next := curr.Next + curr.Next = prev + prev = curr + curr = next + } + + // Step 3: walk the first half (from head) and the reversed second half + // (from prev) together, summing each twin pair and keeping the max. + maxSum := 0 + first, second := head, prev + for second != nil { + if sum := first.Val + second.Val; sum > maxSum { + maxSum = sum + } + first = first.Next + second = second.Next + } + return maxSum +} diff --git a/problems/2130-maximum-twin-sum-of-a-linked-list/solution_test.go b/problems/2130-maximum-twin-sum-of-a-linked-list/solution_test.go new file mode 100644 index 0000000..1117124 --- /dev/null +++ b/problems/2130-maximum-twin-sum-of-a-linked-list/solution_test.go @@ -0,0 +1,41 @@ +package main + +import "testing" + +// buildList constructs a linked list from a slice of values and returns its head. +func buildList(vals []int) *ListNode { + dummy := &ListNode{} + curr := dummy + for _, v := range vals { + curr.Next = &ListNode{Val: v} + curr = curr.Next + } + return dummy.Next +} + +func TestSolution(t *testing.T) { + tests := []struct { + name string + input []int + expected int + }{ + {"example 1: [5,4,2,1] outer pairs all sum to 6", []int{5, 4, 2, 1}, 6}, + {"example 2: [4,2,2,3] max of 7 and 4", []int{4, 2, 2, 3}, 7}, + {"example 3: [1,100000] single twin pair", []int{1, 100000}, 100001}, + {"edge case: minimum size two equal nodes", []int{7, 7}, 14}, + {"edge case: all equal values", []int{5, 5, 5, 5}, 10}, + {"edge case: max sum from inner pair", []int{1, 100, 100, 1}, 200}, + {"edge case: longer list six nodes", []int{1, 2, 3, 4, 5, 6}, 7}, + {"edge case: descending values", []int{6, 5, 4, 3, 2, 1}, 7}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + head := buildList(tt.input) + result := pairSum(head) + if result != tt.expected { + t.Errorf("pairSum(%v) = %d, want %d", tt.input, result, tt.expected) + } + }) + } +}