Medium草稿★★★★★O(n) 時間 · O(1) 空間
Linked ListTwo PointersStack
Patterns↔️ 雙指針🥞 堆疊⛓️ 鏈結串列操作
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

2130Maximum Twin Sum Of A Linked ListLinked ListMediumLinked List

在一個長度為偶數 n 的鏈結串列中,第 i 個節點的 twin 是第 n-1-i 個節點。twin sum 是一對 twin 節點值的和。回傳最大的 twin sum。

Example:

Input: head = [5,4,2,1] Output: 6(5+1=6, 4+2=6)

Intuition

TIP

核心思路:找到中點後反轉前半段(或後半段),然後同步遍歷計算 twin sum 的最大值。

Approaches

1. Stack — O(n) / O(n/2)
  • Idea: 用快慢指針找到中點,將前半段壓入 Stack,再遍歷後半段同時彈出 Stack 計算配對和
  • Time: O(n)
  • Space: O(n/2) = O(n)
class Solution {
    fun pairSum(head: ListNode?): Int {
        val stack = ArrayDeque<Int>()
        var slow = head
        var fast = head
        while (fast?.next != null) {
            stack.addLast(slow!!.`val`)
            slow = slow.next
            fast = fast.next?.next
        }
        var maxSum = 0
        var curr = slow
        while (curr != null) {
            maxSum = maxOf(maxSum, curr.`val` + stack.removeLast())
            curr = curr.next
        }
        return maxSum
    }
}
⭐ 2. Reverse First Half — O(n) / O(1)
  • Idea: 快慢指針找中點的同時反轉前半段,然後從中點和反轉後的前半段頭同步遍歷
  • Time: O(n)
  • Space: O(1)
class Solution {
    fun pairSum(head: ListNode?): Int {
        var slow = head
        var fast = head
        var prev: ListNode? = null

        // 快慢指針找中點,同時反轉前半段
        while (fast?.next != null) {
            fast = fast.next?.next
            val next = slow?.next
            slow?.next = prev
            prev = slow
            slow = next
        }

        // prev 是反轉後的前半段頭,slow 是後半段頭
        var maxSum = 0
        var left = prev
        var right = slow
        while (left != null && right != null) {
            maxSum = maxOf(maxSum, left.`val` + right.`val`)
            left = left.next
            right = right.next
        }
        return maxSum
    }
}

🔑 Takeaways