diff --git a/src/main/java/com/thealgorithms/misc/PalindromeSinglyLinkedList.java b/src/main/java/com/thealgorithms/misc/PalindromeSinglyLinkedList.java index 07286b39f..8af8a9b03 100644 --- a/src/main/java/com/thealgorithms/misc/PalindromeSinglyLinkedList.java +++ b/src/main/java/com/thealgorithms/misc/PalindromeSinglyLinkedList.java @@ -30,4 +30,47 @@ public final class PalindromeSinglyLinkedList { return true; } + + // Optimised approach with O(n) time complexity and O(1) space complexity + + public static boolean isPalindromeOptimised(Node head) { + if (head == null || head.next == null) { + return true; + } + Node slow = head; + Node fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + Node midNode = slow; + + Node prevNode = null; + Node currNode = midNode; + Node nextNode; + while (currNode != null) { + nextNode = currNode.next; + currNode.next = prevNode; + prevNode = currNode; + currNode = nextNode; + } + Node left = head; + Node right = prevNode; + while (left != null && right != null) { + if (left.val != right.val) { + return false; + } + right = right.next; + left = left.next; + } + return true; + } + static class Node { + int val; + Node next; + Node(int val) { + this.val = val; + this.next = null; + } + } } diff --git a/src/test/java/com/thealgorithms/misc/PalindromeSinglyLinkedListTest.java b/src/test/java/com/thealgorithms/misc/PalindromeSinglyLinkedListTest.java index ae0d6ae06..0f0577d39 100644 --- a/src/test/java/com/thealgorithms/misc/PalindromeSinglyLinkedListTest.java +++ b/src/test/java/com/thealgorithms/misc/PalindromeSinglyLinkedListTest.java @@ -7,6 +7,8 @@ import com.thealgorithms.datastructures.lists.SinglyLinkedList; import org.junit.jupiter.api.Test; public class PalindromeSinglyLinkedListTest { + + // Stack-based tests @Test public void testWithEmptyList() { assertTrue(PalindromeSinglyLinkedList.isPalindrome(new SinglyLinkedList())); @@ -67,4 +69,74 @@ public class PalindromeSinglyLinkedListTest { exampleList.insert(20); assertFalse(PalindromeSinglyLinkedList.isPalindrome(exampleList)); } + + // Optimized approach tests + @Test + public void testOptimisedWithEmptyList() { + assertTrue(PalindromeSinglyLinkedList.isPalindromeOptimised(null)); + } + + @Test + public void testOptimisedWithSingleElement() { + PalindromeSinglyLinkedList.Node node = new PalindromeSinglyLinkedList.Node(100); + assertTrue(PalindromeSinglyLinkedList.isPalindromeOptimised(node)); + } + + @Test + public void testOptimisedWithOddLengthPositive() { + PalindromeSinglyLinkedList.Node node1 = new PalindromeSinglyLinkedList.Node(1); + PalindromeSinglyLinkedList.Node node2 = new PalindromeSinglyLinkedList.Node(2); + PalindromeSinglyLinkedList.Node node3 = new PalindromeSinglyLinkedList.Node(1); + node1.next = node2; + node2.next = node3; + assertTrue(PalindromeSinglyLinkedList.isPalindromeOptimised(node1)); + } + + @Test + public void testOptimisedWithOddLengthPositive2() { + PalindromeSinglyLinkedList.Node node1 = new PalindromeSinglyLinkedList.Node(3); + PalindromeSinglyLinkedList.Node node2 = new PalindromeSinglyLinkedList.Node(2); + PalindromeSinglyLinkedList.Node node3 = new PalindromeSinglyLinkedList.Node(1); + PalindromeSinglyLinkedList.Node node4 = new PalindromeSinglyLinkedList.Node(2); + PalindromeSinglyLinkedList.Node node5 = new PalindromeSinglyLinkedList.Node(3); + node1.next = node2; + node2.next = node3; + node3.next = node4; + node4.next = node5; + assertTrue(PalindromeSinglyLinkedList.isPalindromeOptimised(node1)); + } + + @Test + public void testOptimisedWithEvenLengthPositive() { + PalindromeSinglyLinkedList.Node node1 = new PalindromeSinglyLinkedList.Node(10); + PalindromeSinglyLinkedList.Node node2 = new PalindromeSinglyLinkedList.Node(20); + PalindromeSinglyLinkedList.Node node3 = new PalindromeSinglyLinkedList.Node(20); + PalindromeSinglyLinkedList.Node node4 = new PalindromeSinglyLinkedList.Node(10); + node1.next = node2; + node2.next = node3; + node3.next = node4; + assertTrue(PalindromeSinglyLinkedList.isPalindromeOptimised(node1)); + } + + @Test + public void testOptimisedWithOddLengthNegative() { + PalindromeSinglyLinkedList.Node node1 = new PalindromeSinglyLinkedList.Node(1); + PalindromeSinglyLinkedList.Node node2 = new PalindromeSinglyLinkedList.Node(2); + PalindromeSinglyLinkedList.Node node3 = new PalindromeSinglyLinkedList.Node(2); + node1.next = node2; + node2.next = node3; + assertFalse(PalindromeSinglyLinkedList.isPalindromeOptimised(node1)); + } + + @Test + public void testOptimisedWithEvenLengthNegative() { + PalindromeSinglyLinkedList.Node node1 = new PalindromeSinglyLinkedList.Node(10); + PalindromeSinglyLinkedList.Node node2 = new PalindromeSinglyLinkedList.Node(20); + PalindromeSinglyLinkedList.Node node3 = new PalindromeSinglyLinkedList.Node(20); + PalindromeSinglyLinkedList.Node node4 = new PalindromeSinglyLinkedList.Node(20); + node1.next = node2; + node2.next = node3; + node3.next = node4; + assertFalse(PalindromeSinglyLinkedList.isPalindromeOptimised(node1)); + } }