Reorder Linked List in DSA Javascript - Time & Space Complexity
We want to understand how the time needed to reorder a linked list changes as the list gets bigger.
Specifically, how the steps grow when we rearrange nodes in a special order.
Analyze the time complexity of the following code snippet.
function reorderList(head) {
if (!head) return;
let slow = head, fast = head;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
let prev = null, curr = slow;
while (curr) {
let next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
let first = head, second = prev;
while (second && second.next) {
let tmp1 = first.next;
let tmp2 = second.next;
first.next = second;
second.next = tmp1;
first = tmp1;
second = tmp2;
}
}
This code reorders a linked list by first finding the middle, reversing the second half, then merging the two halves alternately.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Three loops: one to find the middle, one to reverse the second half, and one to merge lists.
- How many times: Each loop runs roughly n/2 times, where n is the number of nodes.
As the list size grows, each of the three loops processes about half the list, so total steps grow roughly in a straight line with n.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 15 steps (3 loops x ~5 each) |
| 100 | About 150 steps (3 loops x ~50 each) |
| 1000 | About 1500 steps (3 loops x ~500 each) |
Pattern observation: The total work grows linearly as the list gets longer.
Time Complexity: O(n)
This means the time to reorder the list grows directly in proportion to the number of nodes.
[X] Wrong: "Reversing the second half or merging lists takes more than linear time because it looks like nested loops."
[OK] Correct: Each loop runs separately over different parts of the list, not nested inside each other, so total time adds up linearly, not multiplies.
Understanding this linear time complexity helps you explain efficient list manipulations clearly and confidently in interviews.
"What if we used recursion to reverse the second half instead of a loop? How would the time complexity change?"
Practice
Reorder Linked List problem?Solution
Step 1: Understand the problem goal
The problem asks to reorder nodes so the first node is followed by the last node, then second node, then second last, and so on.Step 2: Differentiate from other operations
This is not sorting or reversing the whole list, but alternating nodes from front and back.Final Answer:
Rearrange the list so nodes alternate from start and end towards the center -> Option AQuick Check:
Reorder Linked List = Alternate front and back nodes [OK]
- Confusing reorder with sorting
- Trying to reverse the entire list only
- Ignoring the alternating pattern
Solution
Step 1: Use two pointers to find middle
Initialize two pointers: slow moves one step, fast moves two steps until fast reaches end.Step 2: Check each option
let slow = head, fast = head; while(fast && fast.next) { slow = slow.next; fast = fast.next.next; } correctly moves slow by one and fast by two steps in the loop condition.Final Answer:
let slow = head, fast = head; while(fast && fast.next) { slow = slow.next; fast = fast.next.next; } -> Option DQuick Check:
Fast moves twice, slow moves once to find middle [OK]
- Moving slow pointer incorrectly
- Not checking fast and fast.next in loop condition
- Starting fast pointer incorrectly
Solution
Step 1: Identify the reorder pattern
The reorder pattern is first node, last node, second node, second last node, and so on.Step 2: Apply pattern to list 1->2->3->4
Start with 1, then 4, then 2, then 3, resulting in 1 -> 4 -> 2 -> 3 -> null.Final Answer:
1 -> 4 -> 2 -> 3 -> null -> Option CQuick Check:
Alternate front and back nodes = 1->4->2->3 [OK]
- Reversing the entire list instead
- Not alternating nodes correctly
- Leaving list unchanged
function reorderList(head) {
if (!head) return;
let slow = head, fast = head;
while (fast.next && fast.next.next) {
slow = slow.next;
fast = fast.next.next;
}
let second = slow.next;
slow.next = null;
second = reverseList(second);
let first = head;
while (second) {
let temp1 = first.next;
let temp2 = second.next;
first.next = second;
second.next = temp1;
first = temp1;
second = temp2;
}
}
function reverseList(head) {
let prev = null;
while (head) {
let next = head.next;
head.next = prev;
prev = head;
head = next;
}
return prev;
}
What is the bug in this code?Solution
Step 1: Analyze the merging loop
The merging loop assumes first is never null, but if first becomes null before second, it causes errors.Step 2: Identify missing null check
There is no check if first is null before accessing first.next, which can cause runtime errors.Final Answer:
The merging loop does not handle the case when first becomes null -> Option AQuick Check:
Merging loop must check first != null to avoid errors [OK]
- Ignoring null checks in merging loop
- Thinking reverseList is faulty
- Misreading middle finding loop condition
Solution
Step 1: Understand reorder pattern for odd length list
For odd length, reorder as first node, last node, second node, second last node, then middle node.Step 2: Apply to list 1->2->3->4->5
Sequence: 1 (first), 5 (last), 2 (second), 4 (second last), 3 (middle).Final Answer:
1 -> 5 -> 2 -> 4 -> 3 -> null -> Option BQuick Check:
Alternate front and back nodes with middle last [OK]
- Reversing entire list
- Not handling odd length middle node correctly
- Leaving list unchanged
Ready to prove it?
Pass the test and this pattern moves unknown
