Intermediate
Open
Free
Palindromic Linked List
Given the head of a singly linked list, determine whether it reads the
same forwards and backwards (i.e., its sequence of values is a
palindrome). Return True or False.
Example 1
Input: 1 -> 2 -> 2 -> 1 -> None
Output: True
Example 2
Input: 1 -> 2 -> 3 -> None
Output: False
Example 3
Input: 7 -> None
Output: True
Constraints
- The number of nodes is in the range
[1, 10^5]. 0 <= Node.val <= 9.- Solve it in O(n) time. As a follow-up, try O(1) extra space instead of copying values into an array.
Solution
Copying all values into a Python list and checking values == values[::-1] works in O(n) time but uses O(n) extra space. The O(1)
space approach reuses the reversal idiom from earlier in this subject:
- Find the middle of the list using the classic slow/fast
"runner" two-pointer technique —
slowadvances one node per step,fastadvances two, so whenfastreaches the end,slowis at the midpoint. - Reverse the second half of the list in place (same rewiring loop as the Linked List Reversal problem).
- Walk the first half and the reversed second half together, comparing values; if any pair differs, it's not a palindrome.
- (Optional but polite) reverse the second half back and reattach it, restoring the original list structure.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
def is_palindrome(head: ListNode | None) -> bool:
if head is None or head.next is None:
return True
# Step 1: find the middle with slow/fast pointers.
slow, fast = head, head
while fast.next is not None and fast.next.next is not None:
slow = slow.next
fast = fast.next.next
# Step 2: reverse the second half, starting after slow.
def reverse(node):
prev = None
while node is not None:
nxt = node.next
node.next = prev
prev = node
node = nxt
return prev
second_half = reverse(slow.next)
# Step 3: compare first half against reversed second half.
first, second = head, second_half
is_pal = True
while second is not None:
if first.val != second.val:
is_pal = False
break
first = first.next
second = second.next
# Step 4 (optional): restore the list.
slow.next = reverse(second_half)
return is_pal
Complexity: O(n) time — finding the middle, reversing half the list, and comparing are each O(n) or less. O(1) extra space, since the reversal is done in place and only a constant number of pointers are used.
Share this question