Linked Lists · Linked List Fundamentals

Linked List Palindrome Check

Combining fast/slow traversal and in-place reversal to check whether a singly linked list reads the same forwards and backwards, in O(1) extra space.

  • 5 min read
  • 11 practice questions
  • 2 graded problems
On this page
  1. Description
  2. The approach
  3. A second flavor: interleaving instead of comparing
  4. Where you'll see it
  5. Which tool for which job?
  6. Common mistakes
  7. Check yourself
  8. Key takeaways
  9. Quick revise
  10. Practice

Description

Checking whether a singly linked list is a palindrome looks like it needs walking backwards, which the list can't do. Instead, combine two moves you already know. Find the middle with fast and slow pointers, reverse the second half in place, and compare the two halves from the outside in. Swap the comparison for an interleaving merge, and the same moves solve Reorder List.

We'll go from simple to more technical:

  1. The pattern: middle, reverse the second half, compare.
  2. A second flavor: interleave the halves instead (Reorder List).
  3. Why composing small building blocks is a habit worth having.
  4. The details that differ between the two uses: odd middles, the cut, and restoring the list.

The approach

A palindrome reads the same both ways. So the second half, read backwards, must match the first half read forwards. You can't read a singly linked list backwards, but you can reverse its second half in place and then read it forwards.

Checking 3 -> 8 -> 5 -> 8 -> 3:

StepWhat happens
1. Find the middlefast and slow pointers: slow stops on 5
2. Reverse from the middlethe back half 5 -> 8 -> 3 becomes 3 -> 8 -> 5
3. Compare from both fronts3 = 3, 8 = 8, 5 = 5: the reversed half is used up, so it's a palindrome

For 3 -> 8 -> 5 -> 2 -> 3, the reversed back half is 3 -> 2 -> 5, and the second comparison, 8 against 2, fails. With an odd length, the middle node ends up compared with itself, so it needs no special case.

1. Find the middle with fast/slow pointers (see two-pointer-list-traversal).
2. Reverse the second half in place (see singly-linked-list-basics).
3. Walk the original first half and the reversed second half together,
   comparing values - any mismatch means it's not a palindrome.

Nothing new is invented here. "Find the middle" says where to split, and "reverse in place" turns the back half into something you can read forwards.

A second flavor: interleaving instead of comparing

Keep the same first two moves, but change the third. Instead of comparing the halves, weave them together. That reorders L0, L1, ..., Ln into L0, Ln, L1, Ln-1, L2, .... For example, 3 -> 8 -> 5 -> 2 -> 6 becomes 3 -> 6 -> 8 -> 2 -> 5.

Java

ListNode secondHead = slow.next;
slow.next = null;                      // cut the first half away from the second
ListNode second = reverse(secondHead);  // same reversal building block as before
ListNode first = head;
while (second != null) {
    ListNode t1 = first.next, t2 = second.next;
    first.next = second;
    second.next = t1;
    first = t1;
    second = t2;
}

Python

second_head = slow.next
slow.next = None                        # cut the first half away from the second
second = reverse(second_head)           # same reversal building block as before
first = head
while second is not None:
    t1, t2 = first.next, second.next
    first.next = second
    second.next = t1
    first, second = t1, t2

One new detail: cut the first half off from the second (slow.next = null) before reversing and weaving. Comparing never changes any next, so a leftover link did no harm there. Weaving rewires next pointers, and a leftover link turns into a cycle.

Where you'll see it

The lesson here is the habit more than the problem. Most medium interview problems, and a lot of production code, combine a few small, well-understood pieces. When a task looks new, ask which building blocks it's made of before inventing anything.

Which tool for which job?

You needUse
Palindrome check, O(1) spacemiddle + reverse second half + compare
The same, simplest codecopy the values into an array and compare ends
The caller's list unchangedreverse the second half back afterwards
A check over a stream you read onceforward and backward rolling hashes
Reorder L0, Ln, L1, Ln-1, ...middle + cut + reverse + interleave

Common mistakes

MistakeWhat happensDo this instead
Worrying about the odd middleextra code for nothingit matches itself - compare until the reversed half ends
Leaving the list half-reversedthe caller sees a shorter, broken listreverse the second half back
No cut before interleavinga cycle appearsset the first half's last next to null
Reading the list while another thread checks itthe reader sees the half-reversed listcopy, or don't mutate shared lists
Comparing past the reversed halfnull dereferenceloop while the second pointer isn't null

Check yourself

Try to answer before opening each one - recalling beats re-reading.

1. With an odd number of nodes, why doesn't the middle node need a match?

Show answer

Reversing from the middle puts the middle node at the end of both halves you compare. When the walk reaches it, it's compared with itself, which always matches. So no special case is needed.

2. The check must leave the caller's list unchanged. What extra step does the reversal method need?

Show answer

Reverse the second half back before returning. The in-place reversal really changed the list's links, not just how you read them. Copying the values into an array never touches the list, which is the trade-off: simpler, but O(n) extra space.

3. Why does weaving the halves need a cut first, when comparing them doesn't?

Show answer

Comparing only reads values and never changes a next, so an uncut link is never followed. Weaving reassigns next pointers. An uncut link from the first half into the second then becomes part of a cycle.

Key takeaways

  • A palindrome check combines two known moves: find the middle, reverse in place. Then compare.
  • The same moves with a different last step reorder the list instead.
  • An odd middle node is compared with itself, so it needs no special case.
  • The reversal changes the list. Reverse it back if the caller needs it intact.
  • Cut the halves apart before any step that rewires them.

Quick revise

The whole skill on one page, for the night before an interview.

Everything from the lesson and the deep dive on one page. Skim it before practice or an interview, and open the full lesson for anything that doesn't ring a bell.

Pick the tool

You needUse
O(1) spacemiddle + reverse + compare
Simplestan array of values
List unchangedreverse back afterwards
A read-once streamforward/backward rolling hashes
Reorder Listmiddle + cut + reverse + interleave

Snippets worth knowing by heart

Java

ListNode slow = head, fast = head;
while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; }
ListNode second = reverse(slow), p = head, q = second;
boolean ok = true;
while (q != null) { if (p.val != q.val) { ok = false; break; } p = p.next; q = q.next; }
reverse(second);               // put the caller's list back
return ok;

Python

slow = fast = head
while fast and fast.next:
    slow, fast = slow.next, fast.next.next
second = reverse(slow)
p, q, ok = head, second, True
while q:
    if p.val != q.val:
        ok = False
        break
    p, q = p.next, q.next
reverse(second)                # put the caller's list back
return ok

The traps

  • Special-casing the odd middle: it's extra code for nothing, since the middle matches itself. Compare until the reversed half ends.
  • Not restoring the list: the caller sees a shorter, broken list. Reverse the second half back.
  • No cut before interleaving: the list gains a cycle. Set the first half's last next to null.
  • Shared lists read by others: another reader sees the half-reversed list. Copy it, or don't mutate.
  • Comparing past the reversed half: you dereference null. Loop while the second pointer isn't null.

Staff-level points, one line each

  • Unrestored, the caller saw [1, 2, 3] instead of [1, 2, 3, 2, 1].
  • Restore on every return path - a check shouldn't mutate its input.
  • Other threads see a broken list during the check.
  • Rolling hashes: one pass, no mutation; 0 disagreements on 10,000 lists.

Say it in an interview

  • "I find the middle, reverse the second half, and compare from both ends."
  • "The odd middle compares with itself, so no special case."
  • "I reverse the second half back so the caller's list is unchanged."
  • "It's O(n) time and O(1) extra space."

Practice

This skill comes with 11 multiple-choice questions that tell you which misconception a wrong answer reveals and 2 graded problems. Your answers are graded and your mastery is tracked, so you'll know when the skill holds up. Running code and saving progress need a free account.

Practice Linked List Palindrome Check free

Palindrome Linked List

MediumProCoding problemJava · Python

Return whether a singly linked list holds the same sequence of values read from either end.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Reorder List

MediumProCoding problemJava · Python

Rearrange a linked list in place so it alternates between the front and the back: the first node, then the last, then the second, then the second-to-last, and so on.

The full statement, the examples and the hidden test suite are part of AI Proof Engineers Pro.

Practice Linked List Palindrome Check free

No card needed. Lessons, practice questions and easy problems are free forever.

Free plan, no card · 7-day Pro trial · Cancel anytime