You are given the head of a singly linked-list. The list can be represented as:
L0 → L1 → … → Ln - 1 → Ln
Reorder the list to be on the following form:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
You may not modify the values in the list's nodes. Only nodes themselves may be changed.
Example 1:
Input: head = [1,2,3,4] Output: [1,4,2,3]
Example 2:
Input: head = [1,2,3,4,5] Output: [1,5,2,4,3]
Constraints:
- The number of nodes in the list is in the range
[1, 5 * 104]
. 1 <= Node.val <= 1000
题目要求重组一个链表,把链表节点从中间分成前后两个部分,把后半部分的节点颠倒顺序,然后挨个插入前半部分每两个节点之间。根据题意,解题思路跟LeetCode 86. Partition List 有点类似,都是先把链表分成两部分然后按一定规则再合并成一个链表。
1)将链表从中间节点分成两部分,可以利用快慢指针来找中间节点,快指针一次走两步慢指针一次走一步,当快指针走到尾部不能再走时,慢指针指向的节点就是中间节点(对于节点个数是偶数的链表,中间有两个节点,慢指针指向的是两个中的第二个,但这不影响处理)。找到中间节点后就把链表分成了两部分:从头节点到中间节点,从中间节点到尾节点。
2)反转链表的第二部分即反转从中间节点到尾节点。可参考LeetCode 206. Reverse Linked List
注意两部分都含有中间节点,反转后中间节点的next指向了空节点,实际上该中间节点就是最后合并后的新链表的尾节点,刚好它的next需要指向空。
3)把第二部分的节点插入第一部分的间隔中。注意,由于反转后的第二部分的最后一个节点也就是中间节点已经在第一部分了末尾了,所以不需要处理可作为终止判断条件。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reorderList(self, head: Optional[ListNode]) -> None:
"""
Do not return anything, modify head in-place instead.
"""
if not head or not head.next:
return
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
pre, cur = None, slow
while cur:
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
p1, p2 = head, pre
while p2.next:
tmp = p2.next
p2.next = p1.next
p1.next = p2
p1 = p2.next
p2 = tmp