在问 · 算法题解

328. 奇偶链表

题目描述

输入一个单链表的头节点 head,链表用数组表示,例如 [1,2,3]。节点按位置从 1 开始编号:第 1 个节点算奇数位,第 2 个算偶数位,依次类推。注意这里看的是位置编号,与节点里存的值无关。

请重排链表:先依次放所有奇数位上的节点,再接上所有偶数位上的节点。每一组内部要保持节点在原链表中的先后顺序。

返回重排后链表的头节点。链表可以为空。要求只用 O(1) 的额外空间,时间复杂度为 O(n)。

示例 1
输入:head = [1,2,3,4,5]
输出:[1,3,5,2,4]

解释:奇数位节点是 1,3,5,偶数位节点是 2,4,前者在前,后者接在后面。

示例 2
输入:head = [2,1,3,5,6,4,7]
输出:[2,3,6,7,1,5,4]

解释:奇数位依次是 2,3,6,7,偶数位依次是 1,5,4,拼起来得到输出。

数据范围

  • n 为链表节点数
  • 0 <= n <= 10^4
  • -10^6 <= Node.val <= 10^6

解题思路

把一条链拆成两条:odd 串起奇数位节点,even 串起偶数位节点,并记住偶数链的头 even_head。每轮让 odd 跳过一个节点接到 even.next,再让 even 跳过一个节点接到 odd.next,两者交替前进。最后把奇数链的尾巴接到 even_head 上。

为什么正确

每轮开始时,odd 是奇数链的尾巴,even 是偶数链的尾巴,并且 odd.next == even,原链上还没处理的部分从 even.next 开始。

复杂度分析

时间 O(n),每个节点只被重新链接一次;额外空间 O(1),只用了几个指针。

易错点

一定要提前保存 even_head,因为循环过程中 even 一直在往后走,最后就找不到偶数链的头了。循环条件要写 even and even.next:节点数为奇数时,even 先变成 None;为偶数时,even.next 先变成 None。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head:
            return head
        odd = head
        even_head = even = head.next
        while even and even.next:
            odd.next = even.next
            odd = odd.next
            even.next = odd.next
            even = even.next
        odd.next = even_head
        return head

载入编辑器,自己跑一遍 →

链表 专题的其他题目

查看 链表 全部题目 →