Palindrome Linked List
You're given the head of a singly linked list of integers. Return true if the values read the same from head to tail as from tail to head, and false otherwise. A one-node list is a palindrome. Aim for O(n) time and O(1) extra space, which rules out copying the values into an array and comparing that.
Examples
head = [1,2,2,1] returns true
Forward the values are 1,2,2,1 and backward they are 1,2,2,1. The first value matches the last and the second matches the third.
head = [1,2] returns false
Forward reads 1,2 but backward reads 2,1. The first value 1 does not equal the last value 2.
head = [1,2,3,2,1] returns true
Both directions read 1,2,3,2,1. With an odd length the middle 3 has no partner, so it never needs to match anything.
Constraints
- 1 <= n <= 10^5
Hints
Could you transform the second half so a single forward scan tells you the answer?
Find the middle with slow/fast, reverse the second half, then compare both halves node by node.
Advance slow/fast to locate the middle. Reverse the list starting at slow using the standard prev/curr swap. Walk left from head and right from the reversed head; mismatch returns false. If you finish the second half, return true.
Drill This: Your Approach First
Approach
Advance slow one node and fast two nodes at a time until fast runs out; slow then sits at the start of the second half (the middle node when the length is odd). Reverse the list from slow onward, then walk one pointer from head and one from the reversed half, comparing values until the reversed half ends. Any mismatch returns false. O(n) time, O(1) extra space, though the list is left with its second half reversed.
Time
O(n)
Space
O(1)
Pitfall
Solutions
class Solution {
public boolean isPalindrome(ListNode head) {
ListNode slow = head, fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode prev = null, curr = slow;
while (curr != null) {
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
ListNode left = head, right = prev;
while (right != null) {
if (left.val != right.val) return false;
left = left.next;
right = right.next;
}
return true;
}
}class Solution:
def isPalindrome(self, head) -> bool:
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
prev, curr = None, slow
while curr:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
left, right = head, prev
while right:
if left.val != right.val:
return False
left = left.next
right = right.next
return True