Linked List
Reorder List
DESCRIPTION (inspired by Leetcode.com)
Given a reference head of type ListNode that is the head of a singly linked list, reorder the list in-place such that the nodes are reordered to form the following pattern:
1st node -> last node -> 2nd node -> 2nd to last node -> 3rd node ...
Example 1: input:
output:
Example 2: input:
output:
Solution
- Finding the middle of the linked list (using fast and slow pointers).
- Reversing the nodes between the middle and the end of the linked list.
- Merging the first half of the linked list with the reversed second half.
Step 1: Find the Middle of the Linked List
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
initialize pointers
0 / 2
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
initialize pointers
0 / 2
Step 2: Reverse second half of list
- save the next node in the iteration by setting next_ = curr.next
- reverse the pointer by setting curr.next = prev
- move pointers for the next iteration by set curr = next_ and prev = curr
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
fast = fast.next.next, slow = slow.next
0 / 10
Step 3: Merge first half with reversed second half
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
curr = next_, prev = curr
0 / 1
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
first = head, second = prev
0 / 1
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
first.next = 1, first = 4
0 / 1
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
second.next = 4, second = 2
0 / 3
Implementation
def reorderList(head):if not head or not head.next:return# Step 1: Find the middle of the list using slow/fast pointersslow = headfast = headwhile fast.next and fast.next.next:slow = slow.nextfast = fast.next.next# Step 2: Reverse the second half starting from slow.nextsecond_half = reverse_list(slow.next)slow.next = None # Cut the list into two halves# Step 3: Merge two halves alternatelyfirst_half = headwhile second_half:first_next = first_half.next # Store next nodessecond_next = second_half.nextfirst_half.next = second_half # Link first to secondsecond_half.next = first_next # Link second to first's nextfirst_half = first_next # Move to next nodessecond_half = second_nextdef reverse_list(head):prev = Nonecurrent = headwhile current:next_temp = current.nextcurrent.next = prevprev = currentcurrent = next_tempreturn prev
Code
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
reorder list
0 / 19
Edge Cases
Empty List
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
reorder list
0 / 1
Single Node
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
reorder list
0 / 1
Two Nodes
- The while loop to find the middle node iterates once, with slow pointing to the 2nd node.
- The while loop to reversing the second half runs once, but since there is only one node in the 2nd half of the list, no pointers are updated, and prev points to the 2nd node.
- The while loop to merge the two halves doesn't run, as second.next is None.
def reorderList(head):if not head or not head.next:return head# find middle nodeslow = fast = headwhile fast and fast.next:fast = fast.next.nextslow = slow.next# reverse second half of listprev, curr = None, slowwhile curr:next_ = curr.nextcurr.next = prevprev, curr = curr, next_# merge first and reversed second half of listfirst, second = head, prevwhile second.next:first.next, first = second, first.nextsecond.next, second = first, second.nextreturn head
reorder list
0 / 8
Test Your Knowledge
Login to take the complexity quiz and track your progress
Complexity Analysis
Time Complexity: O(n) where n is the number of nodes in the linked list. We iterate over the linked list three times: once to find the middle node, once to reverse the second half of the list, and once to merge the two halves together. Each iteration takes O(n) time.
Space Complexity: O(1) We only use a constant amount of extra space to store pointers and temporary variables. Regardless if the linked list has 10 nodes or 10,000 nodes, we will still use two pointers to find the middle node, three pointers to reverse the second half of the list, and two pointers to merge the two halves together.
Mark as read
Your account is free and you can post anonymously if you choose.