Talentd
FleetCode
Make and follow sheets.Sign in

Reorder List solution and explanation

MediumLinked ListRecursionStackTwo Pointers5 min read66.6% acceptanceUpdated 9 Apr 2026
Linkedin Interview Question - Reorder List - Leetcode 143 - PythonNeetCode · 13:47 · 459K viewsWatch on YouTube
9 more videos on this problem
  1. Linkedin Interview Question - Reorder List - Leetcode 143 - PythonNeetCode · 13:47 · 459K views
  2. LeetCode Reorder List Solution Explained - JavaNick White · 12:55 · 35K views
  3. Reorder List (LeetCode 143) | Full Solution with 3 step process and animationsNikhil Lohia · 16:42 · 22K views
  4. Google Coding Interview Question - Reorder List - LeetCode 143AlgoJS · 7:24 · 3K views
  5. Reorder List - LeetCode 143 - Python #reorderlist #leetcode #blind75Deepti Talesra · 13:00 · 3K views
  6. LeetCode 143 | Reorder List | Solution Explained (Whiteboard + Algorithm in Java)Xavier Elon · 7:24 · 2K views
  7. [Java] Leetcode 143. Reorder List [Fast & Slow Pointers #5]Eric Programming · 10:31 · 2K views
  8. reorder list | reorder list leetcode | leetcode 143 | 2 solutions | with stack | reverse second halfNaresh Gupta · 12:34 · 2K views
  9. REORDER LIST | LEETCODE 143 | PYTHON SOLUTIONCracking FAANG · 13:31 · 1K views
  10. Leetcode | 143. Reorder List | Medium | Java SolutionDeveloper Docs · 5:27 · 947 views

The problem

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]

Constraints:

  • The number of nodes in the list is in the range [1, 5 * 104].
  • 1 <= Node.val <= 1000

Approach overview

Problem Overview: You are given the head of a singly linked list. The goal is to reorder nodes so the list follows the pattern L0 → Ln → L1 → Ln-1 → L2 → Ln-2 .... The structure must be modified in-place without changing node values—only pointers can be rearranged.

Approach 1: Using Array List (O(n) time, O(n) space)

This approach copies all nodes into an array-like structure so you can access both ends easily. First iterate through the linked list and push each node into an ArrayList or dynamic array. Then use two pointers: one starting at the beginning and one at the end. Alternate linking nodes from the front and back while moving the pointers inward. Because random access is O(1), the reordering becomes straightforward. The tradeoff is extra memory proportional to the number of nodes. This approach is simple to reason about and helpful when first understanding pointer rearrangement in a linked list.

Approach 2: Reverse Second Half and Merge (O(n) time, O(1) space)

This is the optimal in-place technique and the one most interviewers expect. First find the middle of the list using the classic slow and fast pointer strategy from two pointers. Once the midpoint is located, reverse the second half of the list. Now you have two lists: the original first half and a reversed second half. Finally merge them by alternating nodes—take one node from the first half, then one from the reversed half, and repeat until the lists are exhausted.

The key insight is that reversing the second half allows you to access the last nodes in forward order without using extra memory. Reversal itself runs in O(n) time and constant space by iteratively updating next pointers. During the merge phase, pointers are carefully rewired so nodes interleave correctly without losing references. This technique relies purely on pointer manipulation and avoids auxiliary structures like a stack or array.

Recommended for interviews: The reverse-and-merge approach is the expected solution because it runs in O(n) time and O(1) extra space. Interviewers often want to see if you can combine multiple linked list techniques: finding the middle, reversing a list, and merging two lists. Starting with the array approach demonstrates the core idea, but implementing the in-place method shows stronger mastery of pointer manipulation.

Approach 1: Reverse Second Half and Merge

This approach involves splitting the list into two halves, reversing the second half, and then merging the two lists alternately.

  1. Use the slow and fast pointer technique to find the middle of the list.
  2. Reverse the second half of the list.
  3. Merge the first half of the list with the reversed second half.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def reorderList(self, head: ListNode) -> None:
        if not head:
            return

        slow, fast = head, head.next
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next

        second = slow.next
        prev = slow.next = None
        while second:
            nxt = second.next
            second.next = prev
            prev = second
            second = nxt

        first, second = head, prev
        while second:
            tmp1, tmp2 = first.next, second.next
            first.next = second
            second.next = tmp1
            first, second = tmp1, tmp2
public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

class Solution {
    private ListNode reverseList(ListNode head) {
        ListNode prev = null;
        while (head != null) {
            ListNode next = head.next;
            head.next = prev;
            prev = head;
            head = next;
        }
        return prev;
    }

    public void reorderList(ListNode head) {
        if (head == null || head.next == null) return;
        ListNode slow = head, fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode second = reverseList(slow.next);
        slow.next = null;
        ListNode first = head;
        while (second != null) {
            ListNode tmp1 = first.next;
            ListNode tmp2 = second.next;
            first.next = second;
            second.next = tmp1;
            first = tmp1;
            second = tmp2;
        }
    }
}
#include <iostream>
using namespace std;

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(NULL) {}
};

ListNode* reverseList(ListNode* head) {
    ListNode* prev = NULL;
    while (head) {
        ListNode* next = head->next;
        head->next = prev;
        prev = head;
        head = next;
    }
    return prev;
}

void reorderList(ListNode* head) {
    if (!head || !head->next) return;
    ListNode* slow = head;
    ListNode* fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
    }
    ListNode* second = reverseList(slow->next);
    slow->next = NULL;
    ListNode* first = head;
    while (second) {
        ListNode* tmp1 = first->next;
        ListNode* tmp2 = second->next;
        first->next = second;
        second->next = tmp1;
        first = tmp1;
        second = tmp2;
    }
}
class ListNode {
    constructor(val = 0, next = null) {
        this.val = val;
        this.next = next;
    }
}

function reorderList(head) {
    if (!head || !head.next) return;

    let slow = head, fast = head;
    while (fast && fast.next) {
        slow = slow.next;
        fast = fast.next.next;
    }

    let second = reverseList(slow.next);
    slow.next = null;

    let first = head;
    while (second) {
        let tmp1 = first.next;
        let tmp2 = second.next;
        first.next = second;
        second.next = tmp1;
        first = tmp1;
        second = tmp2;
    }
}

function reverseList(head) {
    let prev = null;
    while (head) {
        let next = head.next;
        head.next = prev;
        prev = head;
        head = next;
    }
    return prev;
}
#include <stdio.h>
#include <stdlib.h>

struct ListNode {
    int val;
    struct ListNode* next;
};

struct ListNode* reverseList(struct ListNode* head) {
    struct ListNode* prev = NULL;
    struct ListNode* current = head;
    while (current) {
        struct ListNode* next = current->next;
        current->next = prev;
        prev = current;
        current = next;
    }
    return prev;
}

void reorderList(struct ListNode* head) {
    if (!head || !head->next) return;
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
    }
    struct ListNode* second = reverseList(slow->next);
    slow->next = NULL;
    struct ListNode* first = head;
    while (second) {
        struct ListNode* tmp1 = first->next;
        struct ListNode* tmp2 = second->next;
        first->next = second;
        second->next = tmp1;
        first = tmp1;
        second = tmp2;
    }
}
public class ListNode {
    public int val;
    public ListNode next;
    public ListNode(int x) { val = x; }
}

public class Solution {
    public void ReorderList(ListNode head) {
        if (head == null || head.next == null) return;
        ListNode slow = head, fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        ListNode second = Reverse(slow.next);
        slow.next = null;
        ListNode first = head;
        while (second != null) {
            ListNode tmp1 = first.next;
            ListNode tmp2 = second.next;
            first.next = second;
            second.next = tmp1;
            first = tmp1;
            second = tmp2;
        }
    }

    private ListNode Reverse(ListNode head) {
        ListNode prev = null;
        while (head != null) {
            ListNode next = head.next;
            head.next = prev;
            prev = head;
            head = next;
        }
        return prev;
    }
}

The Python solution employs a clean and concise approach to rearrange the list according to the specified pattern.

Complexity

Time Complexity: O(n).
Space Complexity: O(1).

Try this approach in the editor

Approach 2: Using Array List

This method involves storing the linked list nodes in an array list and then rearranging their connections to achieve the desired order.

  1. Traverse the linked list and store each node in an array list.
  2. Use two pointers from start and end of the array to relink the nodes in the desired order.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def reorderList(self, head: ListNode) -> None:
        if not head:
            return

        nodes = []
        while head:
            nodes.append(head)
            head = head.next

        left, right = 0, len(nodes) - 1
        while left < right:
            nodes[left].next = nodes[right]
            left += 1
            if left == right:
                break
            nodes[right].next = nodes[left]
            right -= 1
        nodes[left].next = None
public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

class Solution {
    public void reorderList(ListNode head) {
        if (head == null || head.next == null) return;
        List<ListNode> nodes = new ArrayList<ListNode>();
        ListNode node = head;
        while (node != null) {
            nodes.add(node);
            node = node.next;
        }
        int left = 0;
        int right = nodes.size() - 1;
        while (left < right) {
            nodes.get(left).next = nodes.get(right);
            left++;
            if (left == right) break;
            nodes.get(right).next = nodes.get(left);
            right--;
        }
        nodes.get(left).next = null;
    }
}
#include <iostream>
#include <vector>
using namespace std;

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(NULL) {}
};

void reorderList(ListNode* head) {
    if (!head || !head->next) return;
    vector<ListNode*> nodes;
    ListNode* node = head;
    while (node) {
        nodes.push_back(node);
        node = node->next;
    }
    int left = 0, right = nodes.size() - 1;
    while (left < right) {
        nodes[left]->next = nodes[right];
        left++;
        if (left == right) break;
        nodes[right]->next = nodes[left];
        right--;
    }
    nodes[left]->next = nullptr;
}

The Python implementation uses a list to store nodes, then reorders them by alternately connecting nodes from the front and back.

Complexity

Time Complexity: O(n).
Space Complexity: O(n).

Try this approach in the editor

Approach 3: Fast and Slow Pointers + Reverse List + Merge Lists

We first use fast and slow pointers to find the midpoint of the linked list, then reverse the second half of the list, and finally merge the two halves.

The time complexity is O(n), where n is the length of the linked list. The space complexity is O(1).

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     val: number
 *     next: ListNode | null
 *     constructor(val?: number, next?: ListNode | null) {
 *         this.val = (val===undefined ? 0 : val)
 *         this.next = (next===undefined ? null : next)
 *     }
 * }
 */

/**
 Do not return anything, modify head in-place instead.
 */
function reorderList(head: ListNode | null): void {
    let slow = head;
    let fast = head;
    while (fast && fast.next) {
        slow = slow.next;
        fast = fast.next.next;
    }

    let next = slow.next;
    slow.next = null;
    while (next) {
        [next.next, slow, next] = [slow, next, next.next];
    }

    let left = head;
    let right = slow;
    while (right.next) {
        const next = left.next;
        left.next = right;
        right = right.next;
        left.next.next = next;
        left = left.next.next;
    }
}
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reorderList(head *ListNode) {
	fast, slow := head, head
	for fast.Next != nil && fast.Next.Next != nil {
		slow, fast = slow.Next, fast.Next.Next
	}

	cur := slow.Next
	slow.Next = nil

	var pre *ListNode
	for cur != nil {
		t := cur.Next
		cur.Next = pre
		pre, cur = cur, t
	}
	cur = head

	for pre != nil {
		t := pre.Next
		pre.Next = cur.Next
		cur.Next = pre
		cur, pre = pre.Next, t
	}
}
// Definition for singly-linked list.
// #[derive(PartialEq, Eq, Clone, Debug)]
// pub struct ListNode {
//   pub val: i32,
//   pub next: Option<Box<ListNode>>
// }
//
// impl ListNode {
//   #[inline]
//   fn new(val: i32) -> Self {
//     ListNode {
//       next: None,
//       val
//     }
//   }
// }
use std::collections::VecDeque;
impl Solution {
    pub fn reorder_list(head: &mut Option<Box<ListNode>>) {
        let mut tail = &mut head.as_mut().unwrap().next;
        let mut head = tail.take();
        let mut deque = VecDeque::new();
        while head.is_some() {
            let next = head.as_mut().unwrap().next.take();
            deque.push_back(head);
            head = next;
        }
        let mut flag = false;
        while !deque.is_empty() {
            *tail = if flag {
                deque.pop_front().unwrap()
            } else {
                deque.pop_back().unwrap()
            };
            tail = &mut tail.as_mut().unwrap().next;
            flag = !flag;
        }
    }
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Reverse Second Half and Merge

Time Complexity: O(n).
Space Complexity: O(1).

Using Array List

Time Complexity: O(n).
Space Complexity: O(n).

Fast and Slow Pointers + Reverse List + Merge Lists–

Complexity analysis

ApproachTimeSpaceWhen to Use
Using Array ListO(n)O(n)Simpler implementation when extra memory is acceptable
Reverse Second Half and MergeO(n)O(1)Optimal interview solution with constant extra space

Frequently asked questions

Is Reorder List easy or hard?

Reorder List is generally classified as a medium difficulty problem. The challenge comes from combining multiple linked list operations—finding the midpoint, reversing a list, and merging lists—while carefully maintaining pointer references.

How to solve Reorder List in O(n)?

Find the middle of the list using slow and fast pointers, reverse the second half of the list, then merge the two halves by alternating nodes. Each phase—middle detection, reversal, and merge—takes linear time, resulting in overall O(n) complexity with O(1) extra space.

What is the best approach for Reorder List?

The best approach is reversing the second half of the linked list and then merging it with the first half. This technique uses the slow–fast pointer method to find the middle, reverses the second half in place, and alternates nodes during merge. It runs in O(n) time with O(1) extra space, which is considered the optimal solution.

What data structure is used in Reorder List?

The problem is based on a singly linked list. The optimal solution uses pointer manipulation with techniques such as the two-pointer method and in-place list reversal. Some simpler implementations also use an auxiliary array or stack to access nodes from both ends.

What is the time complexity of Reorder List?

The optimal algorithm runs in O(n) time because the list is traversed a constant number of times: once to find the middle, once to reverse the second half, and once to merge the halves. Each step is linear and does not involve nested iteration.

Reorder List Python or Java solution approach?

Python and Java solutions typically implement the reverse-second-half strategy. First locate the middle node with slow and fast pointers, reverse the remaining list iteratively, then interleave nodes from the first half and the reversed second half until the list is reordered.

Is Reorder List asked at Google, Amazon, or Meta?

Reorder List is a common medium-level linked list problem frequently asked in technical interviews. Variants of this pattern have appeared in interviews at companies like Amazon, Meta, and Google because it tests pointer manipulation and multiple linked list techniques in one problem.

Comments

Now write it yourselfClose this page and solve Reorder List in the editor, without looking.
Practise Reorder List