Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions problems/2130-maximum-twin-sum-of-a-linked-list/analysis.md
Original file line number Diff line number Diff line change
@@ -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.
76 changes: 76 additions & 0 deletions problems/2130-maximum-twin-sum-of-a-linked-list/problem.md
Original file line number Diff line number Diff line change
@@ -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`
47 changes: 47 additions & 0 deletions problems/2130-maximum-twin-sum-of-a-linked-list/solution.go
Original file line number Diff line number Diff line change
@@ -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
}
41 changes: 41 additions & 0 deletions problems/2130-maximum-twin-sum-of-a-linked-list/solution_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
})
}
}