package com.freetymekiyan.algorithms.level.easy; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; /** * Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. * <p> * For example, * "A man, a plan, a canal: Panama" is a palindrome. * "race a car" is not a palindrome. * <p> * Note: * Have you consider that the string might be empty? This is a good question to ask during an interview. * <p> * For the purpose of this problem, we define empty string as valid palindrome. * <p> * Company Tags: Microsoft, Uber, Facebook, Zenefits * Tags: Two Pointers, String * Similar Problems: (E) Palindrome Linked List */ public class ValidPalindrome { private ValidPalindrome v; /** * Two pointers. * Ask for clarification: * What characters do we have for input? Space? * Case sensitive or not? * First convert the string to lowercase. * Then start from both ends and move pointers to the next alphanumeric character. * If these characters are not the same, return false. * Remember to move pointers one more step for the next round. */ public boolean isPalindrome(String s) { if (s == null || s.length() == 0) { return true; } int i = 0; int j = s.length() - 1; s = s.toLowerCase(); while (i < j) { // Check current characters. while (i < j && !Character.isLetterOrDigit(s.charAt(i))) { i++; } if (i >= j) { return true; } while (i < j && !Character.isLetterOrDigit(s.charAt(j))) { j--; } if (s.charAt(i) != s.charAt(j)) { return false; } // Move for the next round. i++; j--; } return true; } @Before public void setUp() { v = new ValidPalindrome(); } @Test public void testExamples() { Assert.assertTrue(v.isPalindrome("A man, a plan, a canal: Panama")); Assert.assertFalse(v.isPalindrome("race a car")); } @After public void tearDown() { v = null; } }