diff --git a/src/main/java/com/thealgorithms/strings/Palindrome.java b/src/main/java/com/thealgorithms/strings/Palindrome.java index 3567a371d70e..b570e659c3b0 100644 --- a/src/main/java/com/thealgorithms/strings/Palindrome.java +++ b/src/main/java/com/thealgorithms/strings/Palindrome.java @@ -1,58 +1,104 @@ package com.thealgorithms.strings; -/** - * Wikipedia: https://en.wikipedia.org/wiki/Palindrome - */ -final class Palindrome { +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +public final class Palindrome { + private Palindrome() { } /** - * Check if a string is palindrome string or not using String Builder + * Check if a string is palindrome or not using StringBuilder. * * @param s a string to check - * @return {@code true} if given string is palindrome, otherwise - * {@code false} + * @return {@code true} if given string is palindrome, otherwise {@code false} */ public static boolean isPalindrome(String s) { - return ((s == null || s.length() <= 1) || s.equals(new StringBuilder(s).reverse().toString())); + if (s == null || s.length() <= 1) { + return true; + } + String cleanedString = s.replaceAll("[^a-zA-Z0-9]", "").toLowerCase(); + return cleanedString.equals(new StringBuilder(cleanedString).reverse().toString()); } /** - * Check if a string is palindrome string or not using recursion + * Check if a string is palindrome using optimized recursion (pointer-based). * * @param s a string to check - * @return {@code true} if given string is palindrome, otherwise - * {@code false} + * @return {@code true} if given string is palindrome, otherwise {@code false} */ public static boolean isPalindromeRecursion(String s) { - if (s == null || s.length() <= 1) { + if (s == null) { return true; } + String cleanedString = s.replaceAll("[^a-zA-Z0-9]", "").toLowerCase(); + return isPalindromeRecursion(cleanedString, 0, cleanedString.length() - 1); + } - if (s.charAt(0) != s.charAt(s.length() - 1)) { + private static boolean isPalindromeRecursion(String s, int left, int right) { + if (left >= right) { + return true; + } + if (s.charAt(left) != s.charAt(right)) { return false; } - - return isPalindromeRecursion(s.substring(1, s.length() - 1)); + return isPalindromeRecursion(s, left + 1, right - 1); } /** - * Check if a string is palindrome string or not using two pointer technique + * Check if a string is palindrome using the two-pointer technique. * * @param s a string to check - * @return {@code true} if given string is palindrome, otherwise - * {@code false} + * @return {@code true} if given string is palindrome, otherwise {@code false} */ public static boolean isPalindromeTwoPointer(String s) { if (s == null || s.length() <= 1) { return true; } - for (int i = 0, j = s.length() - 1; i < j; ++i, --j) { - if (s.charAt(i) != s.charAt(j)) { + String cleanedString = s.replaceAll("[^a-zA-Z0-9]", "").toLowerCase(); + int left = 0; + int right = cleanedString.length() - 1; + while (left < right) { + if (cleanedString.charAt(left) != cleanedString.charAt(right)) { return false; } + left++; + right--; } return true; } + + /** + * JUnit Test Cases for the Palindrome methods + */ + public static class PalindromeTest { + + @Test + void testIsPalindrome() { + assertTrue(Palindrome.isPalindrome("madam")); + assertFalse(Palindrome.isPalindrome("hello")); + assertTrue(Palindrome.isPalindrome("A man, a plan, a canal: Panama")); + assertTrue(Palindrome.isPalindrome("")); + assertTrue(Palindrome.isPalindrome("a")); + } + + @Test + void testIsPalindromeRecursion() { + assertTrue(Palindrome.isPalindromeRecursion("racecar")); + assertFalse(Palindrome.isPalindromeRecursion("world")); + assertTrue(Palindrome.isPalindromeRecursion("A man, a plan, a canal, Panama")); + assertTrue(Palindrome.isPalindromeRecursion("a")); + assertTrue(Palindrome.isPalindromeRecursion(null)); + } + + @Test + void testIsPalindromeTwoPointer() { + assertTrue(Palindrome.isPalindromeTwoPointer("madam")); + assertFalse(Palindrome.isPalindromeTwoPointer("hello")); + assertTrue(Palindrome.isPalindromeTwoPointer("A man, a plan, a canal: Panama")); + assertTrue(Palindrome.isPalindromeTwoPointer("a")); + assertTrue(Palindrome.isPalindromeTwoPointer(null)); + } + } }