Given a singly linked list, determine if it is a palindrome.
Java Solution 1 – Creat a new reversed list
We can create a new list in reversed order and then compare each node. The time and space are O(n).
public boolean isPalindrome(ListNode head) { if(head == null) return true; ListNode p = head; ListNode prev = new ListNode(head.val); while(p.next != null){ ListNode temp = new ListNode(p.next.val); temp.next = prev; prev = temp; p = p.next; } ListNode p1 = head; ListNode p2 = prev; while(p1!=null){ if(p1.val != p2.val) return false; p1 = p1.next; p2 = p2.next; } return true; } |
Java Solution 2 – Break and reverse second half
We can use a fast and slow pointer to get the center of the list, then reverse the second list and compare two sublists. The time is O(n) and space is O(1).
public boolean isPalindrome(ListNode head) { if(head == null || head.next==null) return true; //find list center ListNode fast = head; ListNode slow = head; while(fast.next!=null && fast.next.next!=null){ fast = fast.next.next; slow = slow.next; } ListNode secondHead = slow.next; slow.next = null; //reverse second part of the list ListNode p1 = secondHead; ListNode p2 = p1.next; while(p1!=null && p2!=null){ ListNode temp = p2.next; p2.next = p1; p1 = p2; p2 = temp; } secondHead.next = null; //compare two sublists now ListNode p = (p2==null?p1:p2); ListNode q = head; while(p!=null){ if(p.val != q.val) return false; p = p.next; q = q.next; } return true; } |
Java Solution 3 – Recursive
public class Solution { ListNode left; public boolean isPalindrome(ListNode head) { left = head; boolean result = helper(head); return result; } public boolean helper(ListNode right){ //stop recursion if (right == null) return true; //if sub-list is not palindrome, return false boolean x = helper(right.next); if (!x) return false; //current left and right boolean y = (left.val == right.val); //move left to next left = left.next; return y; } } |
Time is O(n) and space is O(n).
obv we can find middle, then unwind recurse , checking nodes
n/2-1 , n/2-2… checking w/ n/2 n/2+1 .. on
keep pointer to 2d half
can be re-reversed back.
it is not size. size can be calculated!,
how do you get j-1 from j!! you need traverse whole range.
it is o(n^2)
can use stack or array/queue, just push half elements, and compare 2d half in reverse.
Reversing half of the list destroys the original list.
how to you know the linkedlist size and index if an unlimited listNode was provided
Recursive solution can’t be O(1) space right?
public boolean isPalindrome(ListNode head) {
if(head == null || head.next == null){
return true;
}
ListNode slow = head;
ListNode fast = head;
while(fast.next != null && fast.next.next != null){
slow = slow.next;
fast = fast.next.next;
}
ListNode reversed = reverseList(slow);
slow.next = null;
ListNode current = head;
while(current != null){
if(reversed != null && current.val != reversed.val){
return false;
}
current = current.next;
reversed = reversed.next;
}
return true;
}
ListNode reverseList(ListNode head){
if(head == null || head.next == null){
return head;
}
ListNode current = head;
ListNode reversed = null;
ListNode nextNode = null;
while(current != null){
nextNode = current.next;
current.next = reversed;
reversed = current;
current = nextNode;
}
return reversed;
}
can we do something like this? the time is O(n) and space is O(1).
public static boolean isPalindrome(LinkedList list){
int i = 0;
int j = list.size() – 1;
while(i<j){
if (!list.get(i).equals(list.get(j))){
return false;
}
i++;
j–;
}
return true;
}
public boolean isPalindromeLinkedList(Node head){
if(head == null){
throw new IllegalArgumentException();
}
if(head.next == null){
return true;
}
Node p1 = head;
Node p2 = head;
Node p = null;
while(p1 = null && p1.next != null){
p1 = p1.next.next;
p = p2;
p2 = p2.next;
}
Node prev = new Node(p2.value);
while(p2.next != null){
Node tmp = new Node(p2.next.value);
tmp.next = prev;
prev = tmp;
p2 = p2.next;
}
p1 = head;
p = p.next;
while(p.next != null){
if(p1 != p){
return false;
}
p1 = p1.next;
p = p.next;
}
return true;
}
I know (;
If you use stack, then the space is O(n) not O(1)
😉
Using Stack:
private boolean isPalindromeUsingStack(ListNode head) {
int count = 0;
ListNode current = head;
while (current!= null) {
current = current.next;
count++;
}
current = head;
// remove the middle node if the count is odd
if (count % 2 == 1) {
for (int i = 0; i < (count/2) - 1 ; i++) {
current = current.next;
}
current.next = current.next.next;
}
// now head has even number of elements
Stack stack = new Stack();
stack.push(head);
current = head.next;
while (current!= null) {
if (current.val == stack.peek().val) {
stack.pop();
} else {
stack.push(current);
}
current = current.next;
}
return stack.isEmpty();
}
Thanks for your code. I also discussion with illustration the problem here http://www.capacode.com/data-structure/linked-list/check-linked-list-palindrome/