Problem Description
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.
Examples
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]
Python Solution
def reorderList(head: Optional[ListNode]) -> None:
if not head or not head.next:
return
# Find middle
slow = fast = head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next
# Reverse second half
prev = None
curr = slow.next
slow.next = None
while curr:
next_temp = curr.next
curr.next = prev
prev = curr
curr = next_temp
# Merge two halves
first = head
second = prev
while second:
next_first = first.next
next_second = second.next
first.next = second
second.next = next_first
first = next_first
second = next_second
Java Solution
class Solution {
public void reorderList(ListNode head) {
if (head == null || head.next == null) {
return;
}
// Find middle
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// Reverse second half
ListNode prev = null;
ListNode curr = slow.next;
slow.next = null;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
// Merge two halves
ListNode first = head;
ListNode second = prev;
while (second != null) {
ListNode nextFirst = first.next;
ListNode nextSecond = second.next;
first.next = second;
second.next = nextFirst;
first = nextFirst;
second = nextSecond;
}
}
}
C++ Solution
class Solution {
public:
void reorderList(ListNode* head) {
if (!head || !head->next) {
return;
}
// Find middle
ListNode* slow = head;
ListNode* fast = head;
while (fast->next && fast->next->next) {
slow = slow->next;
fast = fast->next->next;
}
// Reverse second half
ListNode* prev = nullptr;
ListNode* curr = slow->next;
slow->next = nullptr;
while (curr) {
ListNode* nextTemp = curr->next;
curr->next = prev;
prev = curr;
curr = nextTemp;
}
// Merge two halves
ListNode* first = head;
ListNode* second = prev;
while (second) {
ListNode* nextFirst = first->next;
ListNode* nextSecond = second->next;
first->next = second;
second->next = nextFirst;
first = nextFirst;
second = nextSecond;
}
}
};
JavaScript Solution
/**
* @param {ListNode} head
* @return {void} Do not return anything, modify head in-place instead.
*/
var reorderList = function(head) {
if (!head || !head.next) {
return;
}
// Find middle
let slow = head;
let fast = head;
while (fast.next && fast.next.next) {
slow = slow.next;
fast = fast.next.next;
}
// Reverse second half
let prev = null;
let curr = slow.next;
slow.next = null;
while (curr) {
const nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
// Merge two halves
let first = head;
let second = prev;
while (second) {
const nextFirst = first.next;
const nextSecond = second.next;
first.next = second;
second.next = nextFirst;
first = nextFirst;
second = nextSecond;
}
};
C# Solution
public class Solution {
public void ReorderList(ListNode head) {
if (head == null || head.next == null) {
return;
}
// Find middle
ListNode slow = head;
ListNode fast = head;
while (fast.next != null && fast.next.next != null) {
slow = slow.next;
fast = fast.next.next;
}
// Reverse second half
ListNode prev = null;
ListNode curr = slow.next;
slow.next = null;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
// Merge two halves
ListNode first = head;
ListNode second = prev;
while (second != null) {
ListNode nextFirst = first.next;
ListNode nextSecond = second.next;
first.next = second;
second.next = nextFirst;
first = nextFirst;
second = nextSecond;
}
}
}
Complexity Analysis
- Time Complexity: O(n) where n is the number of nodes in the linked list
- Space Complexity: O(1) as we only use a constant amount of extra space
Solution Explanation
This solution uses three steps:
- Key concept:
- Middle finding
- List reversal
- List merging
- Algorithm steps:
- Find middle node
- Reverse second half
- Merge two halves
- Connect nodes
Key points:
- In-place modification
- Three-step process
- Pointer manipulation
- Constant space