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.
For example, given the linked list 1 -> 2 -> 3 -> 4
, the reordered list should be 1 -> 4 -> 2 -> 3
. If the linked list is 1 -> 2 -> 3 -> 4 -> 5
, the reordered list should be 1 -> 5 -> 2 -> 4 -> 3
.
Describe an algorithm to reorder the linked list in-place, meaning you can only modify the node pointers, not the node values. What is the time and space complexity of your algorithm? Consider edge cases such as an empty list or a list with only one element. Provide a Python implementation of your algorithm.
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]
Code (Python):
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def reorderListNaive(head):
if not head:
return
nodes = []
curr = head
while curr:
nodes.append(curr)
curr = curr.next
i, j = 0, len(nodes) - 1
while i < j:
nodes[i].next = nodes[j]
i += 1
if i >= j:
break
nodes[j].next = nodes[i]
j -= 1
nodes[i].next = None # set the last node's next to None
Time Complexity: O(N), where N is the number of nodes in the linked list.
Space Complexity: O(N), because we store all nodes in an array.
Code (Python):
def reorderListOptimal(head):
if not head or not head.next:
return
# 1. Find middle
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
# 2. Reverse second half
prev, curr = None, slow.next
slow.next = None # break the list into two halves
while curr:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node
# 3. Merge two halves
first, second = head, prev
while second:
temp1, temp2 = first.next, second.next
first.next = second
second.next = temp1
first, second = temp1, temp2
Time Complexity: O(N), where N is the number of nodes in the linked list. Finding the middle, reversing the second half, and merging take O(N) time.
Space Complexity: O(1), because we are doing it in place.