package com.freetymekiyan.algorithms.level.easy; import com.freetymekiyan.algorithms.utils.Utils; import com.freetymekiyan.algorithms.utils.Utils.ListNode; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * Given a singly linked list, determine if it is a palindrome. * <p> * Follow up: * Could you do it in O(n) time and O(1) space? * <p> * Company Tags: Amazon, Facebook * Tags: Linked List, Two Pointers * Similar Problems: (E) Palindrome Number, (E) Valid Palindrome, (E) Reverse Linked List */ public class PalindromeLinkedList { private PalindromeLinkedList p; /** * Two Pointers. * Find the middle node, reverse the right half list, then check each node. * Use two pointers, one slow pointer s, one fast pointer f. * Move s to the head of the right half list. * If there are odd number of nodes, move s one step further. * Reverse the right half of the list starting from s. * Then compare each node's value while s is not null. * If diff, return false. Else continue. * After all nodes checked, return true. */ public boolean isPalindrome(ListNode head) { if (head == null || head.next == null) { return true; } ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; } if (fast != null) { // Make sure slow is always the head of right half. slow = slow.next; } slow = reverseList(slow); // Reverse the right half of the list. ListNode cur = head; while (slow != null) { if (cur.val != slow.val) { return false; } cur = cur.next; slow = slow.next; } return true; } /** * Iterative. * Create a new head as null, which will be the tail of the reversed list. * While head is not null: * | Store the next node. * | Reverse head. * | Update new head. * | Move to next. * Return new head. */ private ListNode reverseList(ListNode head) { ListNode newHead = null; while (head != null) { ListNode next = head.next; head.next = newHead; newHead = head; head = next; } return newHead; } @Before public void setUp() { p = new PalindromeLinkedList(); } @Test public void testExamples() { ListNode h = Utils.buildLinkedList(new int[]{1, 2}); Assert.assertFalse(p.isPalindrome(h)); } @After public void tearDown() { p = null; } }