Reorder Linked List
You are given the head of a singly linked-list.
The positions of a linked list of length = 7 for example, can intially be represented as:
[0, 1, 2, 3, 4, 5, 6]
Reorder the nodes of the linked list to be in the following order:
[0, 6, 1, 5, 2, 4, 3]
Notice that in the general case for a list of length = n the nodes are reordered to be in the following order:
[0, n-1, 1, n-2, 2, n-3, …]
You may not modify the values in the list’s nodes, but instead you must reorder the nodes themselves.
Example 1:
Input: head = [2,4,6,8]
Output: [2,8,4,6]
Example 2:
Input: head = [2,4,6,8,10]
Output: [2,10,4,8,6]
Constraints:
1 <= Length of the list <= 1000.
1 <= Node.val <= 1000
Solution
The process of reorder can be divided into 3 steps:
- Split the linked list into 2 parts: [0, L//2-1], [L//2, L-1]
- Reverse the latter linked list: [0, L//2-1], [L-1, L//2]
- Merge two linked lists in an alternating manner.
An elegant way to split the linked list is to use 2 pointers with different speed. Slow pointer moves 1 node each step and fast one moves 2 node each step. When the fast pointer arrives the end or NULL node, the slow pointer will arrive L//2+1
Code
# 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:
slow, fast = head, head.next # fast=head also works
while fast and fast.next:
slow = slow.next
fast = fast.next.next
half = slow.next
slow.next = None # IMPORTANT! Cut the former half
last = None
while half:
nxt = half.next
half.next = last
last = half
half = nxt
pre = head
while last:
pre_nxt = pre.next
last_nxt = last.next
pre.next = last
last.next = pre_nxt
pre = pre_nxt
last = last_nxt