LeetCode 2130. 链表最大孪生和
题目描述


题意分析
链表长度是正偶数,下标
i与n - 1 - i的两个节点互为孪生节点。需要计算首尾对称的每一对节点值之和,返回其中的最大值。总共只有
n / 2对,不是任选两个节点,也不需要把每一对重复统计。题目保证节点值为正,所以最大和可以从零开始更新;当前实现通过原地反转后半段完成计算,会改变原链表结构。
解法:找中点、反转后半段后计算孪生和
核心思路
[!blue]
前半段需要从头向中间访问,后半段却需要从尾向中间访问,单链表无法直接反向走。将后半段反转,就能让两条指针都沿
next前进,同时取得首尾对称的位置。先让快慢指针都从头开始,分别每轮走两步和一步。长度为偶数时,快指针走完全部
n步,慢指针刚好走到下标n / 2,也就是后半段的第一个节点,不会把前半段节点反转进去。从慢指针位置开始反转,每次先保存原后继,再将当前
next指向已反转部分,最后推进两个指针。反转后prev指向原尾节点,整段顺序变为原下标n - 1、n - 2,直到n / 2。从原头和
prev同步前进,第t轮分别访问原下标t与n - 1 - t,恰好是一对孪生节点。以后半段是否结束控制循环,正好执行n / 2次。虽然原前半段尾部仍连着原中点,但比较会在走出前半段之前结束,不需要为了统计额外断链。
解题步骤
- 快慢指针同从头开始,在快指针及其后继存在时,分别前进两步和一步。
- 慢指针停在后半段头,从这里开始原地反转,改写连接前先保存原后继。
- 原头指针与反转后头指针同步移动,逐对相加并更新最大值。
- 反转后的半条链结束时停止,返回最大孪生和。
代码实现
class Solution {
public int pairSum(ListNode head) {
// 同起点快慢指针:fast 走满 n 步时 slow 恰好走 n/2 步。
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// n 为偶数,slow 精确停在下标 n/2,即后半段的第一个节点。
ListNode prev = null;
while (slow != null) {
ListNode next = slow.next;
slow.next = prev;
prev = slow;
slow = next;
}
int ans = 0;
while (prev != null) {
// 第 t 轮:head 在下标 t,prev 在下标 n-1-t,正好一对孪生节点。
ans = Math.max(ans, head.val + prev.val);
head = head.next;
prev = prev.next;
}
return ans;
}
}
func pairSum(head *ListNode) int {
// 同起点快慢指针:fast 走满 n 步时 slow 恰好走 n/2 步。
slow, fast := head, head
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
// n 为偶数,slow 精确停在下标 n/2,即后半段的第一个节点。
var prev *ListNode
for slow != nil {
next := slow.Next
slow.Next = prev
prev = slow
slow = next
}
ans := 0
for prev != nil {
// 第 t 轮:head 在下标 t,prev 在下标 n-1-t,正好一对孪生节点。
if head.Val+prev.Val > ans {
ans = head.Val + prev.Val
}
head = head.Next
prev = prev.Next
}
return ans
}
复杂度分析
- 时间复杂度:$O(n)$,找中点、反转半条链和成对统计均为线性扫描。
- 空间复杂度:$O(1)$,只保存固定数量的指针与最大值,没有数组或递归栈。
关键点总结
[!green]
- 后半段反转,将首尾相向访问转成两条链同向前进。
- 偶数长度与快慢同起点保证后半段入口准确位于
n / 2。- 反转短链的长度决定比较次数,每轮原下标之和始终为
n - 1。- 本实现只返回统计值,不恢复被反转的连接。
易错点总结
[!yellow]
- 中点规则选成前半段最后节点,并从它开始反转,会破坏配对区间。
- 改写
next后才读取原后继,剩余节点的入口已经丢失。- 一直遍历原头直到空,原链没有显式断成独立前半段,可能超出需要比较的范围。
- 每轮只移动一侧指针,不能保持首尾孪生位置对应。
- 将本题按奇数长度链表设计额外配对规则,题目给定的偶数前提已明确中间没有单独节点。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 234. 回文链表 | 简单 | 同样找中点并反转后半段,原题比较对应值是否相等,本题求对应值和的最大值。 |
| 143. 重排链表 | 中等 | 同样把首尾节点对齐,原题继续交错重连,本题只做成对统计。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!