Copy values into an ArrayList and check it with two pointers.
Approach 1
import java.util.ArrayList;
import java.util.List;
class Solution {
public boolean isPalindrome(ListNode head) {
List<Integer> vals = new ArrayList<>();
for (ListNode p = head; p != null; p = p.next) vals.add(p.val);
for (int i = 0, j = vals.size() - 1; i < j; i++, j--)
if (!vals.get(i).equals(vals.get(j))) return false;
return true;
}
}
Verdict: Easy, but uses O(n) memory.
2
Optimal: reverse the second half
Time O(n) Space O(1)
Fast and slow find the middle. Reverse from slow to the end. Walk from the head and from the reversed half's head together, comparing values.
Approach 2
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; // reverse from slow to the end
while (slow != null) {
ListNode next = slow.next;
slow.next = prev;
prev = slow;
slow = next;
}
for (ListNode a = head, b = prev; b != null; a = a.next, b = b.next)
if (a.val != b.val) return false;
return true;
}
}
Verdict: Constant memory. (Mention that it modifies the list; reverse the half back if the caller needs the original.)
Before you submit
Edge cases and common mistakes
Test these inputs
One node
Two nodes
Odd length (the middle compares with itself)
Mistakes people make
Comparing Integer objects with != in the list version.
Walking the first half until null (it still links into the reversed part); compare until the reversed half ends.