Maximum Twin Sum of a Linked List

題目描述

給定一個偶數長度的 Linked List,節點 i 和節點 n-1-i 互為 twin。回傳最大的 twin sum(twin 兩節點值之和)。

輸入: [5,4,2,1]
輸出: 6
解釋: twin pairs: (5,1), (4,2),最大和 = 5+1 = 6

輸入: [4,2,2,3]
輸出: 7
解釋: twin pairs: (4,3), (2,2),最大和 = 4+3 = 7

解題思路

1

找中點

slow 每走 1 步、fast 走 2 步,fast 到尾時 slow 在中點(後半段起點)

2

反轉後半段

從 slow 開始用 prev/curr 迭代反轉,讓後半段尾變頭

3

配對比較

left 從 head 往右走、right 從反轉後的頭往右走,每步計算 left.val + right.val

4

取最大值

用 maxSum = max(maxSum, left.val + right.val) 持續更新最大 twin sum

程式碼

C#

csharp
public class Solution {
    public int PairSum(ListNode head) {
        // 1. 快慢指針找中點
        var slow = head;
        var fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
 
        // 2. 反轉後半段
        ListNode prev = null;
        while (slow != null) {
            var next = slow.next;
            slow.next = prev;
            prev = slow;
            slow = next;
        }
 
        // 3. 配對比較,求最大 twin sum
        int maxSum = 0;
        var left = head;
        var right = prev;
        while (right != null) {
            maxSum = Math.Max(maxSum, left.val + right.val);
            left = left.next;
            right = right.next;
        }
        return maxSum;
    }
}

TypeScript

typescript
function pairSum(head: ListNode | null): number {
    // 1. 快慢指針找中點
    let slow = head;
    let fast = head;
    while (fast && fast.next) {
        slow = slow!.next;
        fast = fast.next.next;
    }
 
    // 2. 反轉後半段
    let prev: ListNode | null = null;
    while (slow) {
        const next = slow.next;
        slow.next = prev;
        prev = slow;
        slow = next;
    }
 
    // 3. 配對比較,求最大 twin sum
    let maxSum = 0;
    let left = head;
    let right = prev;
    while (right) {
        maxSum = Math.max(maxSum, left!.val + right.val);
        left = left!.next;
        right = right.next;
    }
    return maxSum;
}

Python

python
def pairSum(head: Optional[ListNode]) -> int:
    # 1. 快慢指針找中點
    slow, fast = head, head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
 
    # 2. 反轉後半段
    prev = None
    while slow:
        slow.next, prev, slow = prev, slow, slow.next
 
    # 3. 配對比較,求最大 twin sum
    max_sum = 0
    left, right = head, prev
    while right:
        max_sum = max(max_sum, left.val + right.val)
        left = left.next
        right = right.next
    return max_sum

複雜度分析

| | Time | Space | |--|------|-------| | 本解法 | O(n) | O(1) |

Time 為 O(n) 是因為三個步驟各自遍歷半條鏈表:找中點 n/2 步、反轉 n/2 步、配對比較 n/2 步,合計 3n/2 = O(n)。Space 為 O(1) 是因為反轉在原鏈表上操作,只用了常數個指針。

邊界情況

圖解

5→4→2→1
快慢指針
中點: 2
反轉
後半反轉: 1→2
配對
5+1=6
4+2=6
最大 twin sum = 6

圖表展示了 [5,4,2,1] 的處理流程:先找到中點 2、反轉後半段得到 1→2,然後 left=5 配 right=1(和 6)、left=4 配 right=2(和 6),最大 twin sum 為 6。

進階觀點

💡面試追問

Q: 除了反轉後半段,還有什麼方法? A: 用 Stack 存前半段的值,再遍歷後半段時逐一 pop 配對。空間 O(n/2) = O(n)。也可以把所有值存入 Array 再用雙指針,同樣 O(n) 空間。反轉法是唯一 O(1) 空間的方案。

Q: 反轉後半段會破壞原鏈表,面試時要注意什麼? A: 面試時先問面試官是否允許修改輸入。如果不允許,需要在計算完畢後再反轉一次恢復原狀,或改用 O(n) 空間的方案。

這題結合了三個基礎技巧:快慢指針、反轉 Linked List、雙指針遍歷。面試官常考這種「組合技」。

變體題:LC 234 Palindrome Linked List(同樣技巧,檢查是否回文)。

理解測驗

🤔 為什麼要反轉後半段而不是直接配對?

🤔 如果用 Stack 解這題,空間複雜度會是多少?

你可能也想看

206. Reverse Linked List104. Maximum Depth of Binary Tree

按 ← → 鍵切換課程