给定一个单链表  LL 0→ L 1→…→ L n-1→ L n ,
将其重新排列后变为: L 0→ L n→ L 1→ L n-1→ L 2→ L n-2→…

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3.

示例 2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

">

给定一个单链表 LL0L1→…→Ln-1Ln ,

将其重新排列后变为: L0LnL1Ln-1L2Ln-2→…

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

示例 1:

给定链表 1->2->3->4, 重新排列为 1->4->2->3.

示例 2:

给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.

寻找链表中点 + 链表逆序 + 合并链表

注意到目标链表即为将原链表的左半端和反转后的右半端合并后的结果。

这样我们的任务即可划分为三步:

  1. 找到原链表的中点(参考「876. 链表的中间结点」)。

    • 我们可以使用快慢指针来 O(N)O(N)O(N) 地找到链表的中间节点。
  2. 将原链表的右半端反转(参考「206. 反转链表」)。

    • 我们可以使用迭代法实现链表的反转。
  3. 将原链表的两端合并。

    • 因为两链表长度相差不超过 111,因此直接合并即可。

Code


class Solution:
    def middleNode(self, head: ListNode) -> ListNode:
        slow = fast = head
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next
        return slow

    def reverseList(self, head: ListNode) -> ListNode:
        prev, curr = None, head
        while curr:
            nextTemp = curr.next
            curr.next = prev
            prev = curr
            curr = nextTemp
        return prev

    def mergeList(self, l1: ListNode, l2: ListNode):
        while l1 and l2:
            l1Tmp = l1.next
            l2Tmp = l2.next

            l1.next = l2
            l1 = l1Tmp

            l2.next = l1
            l2 = l2Tmp

    def reorderList(self, head: ListNode) -> None:
        """
        Do not return anything, modify head in-place instead.
        """
        if not head:
            return

        middle = self.middleNode(head)
        l1, l2 = head, middle.next
        middle.next = None
        l2 = self.reverseList(l2)
        self.mergeList(l1, l2)

复杂度分析

  • 时间复杂度:O(N)O(N)O(N),其中 NNN 是链表中的节点数。

  • 空间复杂度:O(1)O(1)O(1)