LeetCode – Valid Palindrome (Java)

Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.

For example, "Red rum, sir, is murder" is a palindrome, while "Programcreek is awesome" is not.

Note:
Have you consider that the string might be empty? This is a good question to ask during an interview.

For the purpose of this problem, we define empty string as valid palindrome.

Thoughts

From start and end loop though the string, i.e., char array. If it is not alpha or number, increase or decrease pointers. Compare the alpha and numeric characters. The solution below is pretty straightforward.

Java Solution 1 - Naive

public class Solution {
 
    public  boolean isPalindrome(String s) {
 
        if(s == null) return false;
        if(s.length() < 2) return true;
 
        char[] charArray = s.toCharArray();
        int len = s.length();
 
        int i=0;
        int j=len-1;
 
        while(i<j){
            char left, right;
 
            while(i<len-1 && !isAlpha(left) && !isNum(left)){
                i++;
                left =  charArray[i];
            }
 
            while(j>0 && !isAlpha(right) && !isNum(right)){
                j--;
                right = charArray[j];
            }
 
            if(i >= j)
            	break;
 
            left =  charArray[i];
            right = charArray[j];
 
            if(!isSame(left, right)){
                return false;
            }
 
            i++;
            j--;
        }
        return true;
    }
 
    public  boolean isAlpha(char a){
        if((a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z')){
            return true;
        }else{
            return false;
        }
    }
 
    public  boolean isNum(char a){
        if(a >= '0' && a <= '9'){
            return true;
        }else{
            return false;
        }
    }
 
    public  boolean isSame(char a, char b){
        if(isNum(a) && isNum(b)){
            return a == b;
        }else if(Character.toLowerCase(a) == Character.toLowerCase(b)){
            return true;
        }else{
            return false;
        }
    }
}

Java Solution 2 - Using Stack

This solution removes the special characters first. (Thanks to Tia)

public boolean isPalindrome(String s) {
	s = s.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
 
	int len = s.length();
	if (len < 2)
		return true;
 
	Stack<Character> stack = new Stack<Character>();
 
	int index = 0;
	while (index < len / 2) {
		stack.push(s.charAt(index));
		index++;
	}
 
	if (len % 2 == 1)
		index++;
 
	while (index < len) {
		if (stack.empty())
			return false;
 
		char temp = stack.pop();
		if (s.charAt(index) != temp)
			return false;
		else
			index++;
	}
 
	return true;
}

Java Solution 3 - Using Two Pointers

In the discussion below, April and Frank use two pointers to solve this problem. This solution looks really simple.

public class ValidPalindrome {
	public static boolean isValidPalindrome(String s){
		if(s==null||s.length()==0) return false;
 
		s = s.replaceAll("[^a-zA-Z0-9]", "").toLowerCase();
		System.out.println(s);
 
		for(int i = 0; i < s.length() ; i++){
			if(s.charAt(i) != s.charAt(s.length() - 1 - i)){
				return false;
			}
		}
 
		return true;
	}
 
	public static void main(String[] args) {
		String str = "A man, a plan, a canal: Panama";
 
		System.out.println(isValidPalindrome(str));
	}
}
Category >> Algorithms  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>

  1. tia on 2014-2-25

    Here is the idea that remove non-letter first

    public class Solution {

    public boolean isPalindrome(String s) {

    s = s.replaceAll(“[^a-zA-Z0-9]”, “”);

    s = s.toLowerCase();

    int len = s.length();

    if(len<2)

    return true;

    Stack sta = new Stack();

    int index = 0;

    while(index < len/2){

    sta.push(s.charAt(index));

    index ++;

    }

    if (len%2 ==1)

    index++;

    while(index < len){

    if(sta.empty())

    return false;

    char temp = sta.pop();

    if(s.charAt(index) != temp)

    return false;

    else

    index ++;

    }

    return true;

    }

    }

  2. ryanlr on 2014-2-26

    Great Solution! Thanks.

  3. Diana Du on 2014-3-6

    Hi, I found that there are two redundant lines in your first solution. These two lines

    “left = charArray[i];

    right = charArray[j];”

    seem to be redundant in the largest while loop, because you have already changed them in the above two while loops.

  4. Frank on 2014-5-27

    public class ValidPalindrome {

    public static boolean isValidPalindrome(String s){

    if(s==null||s.length()==0) return false;

    s = s.replaceAll(“[^a-zA-Z0-9]”, “”).toLowerCase();

    System.out.println(s);

    for(int i = 0; i < s.length() ; i++){

    if(s.charAt(i) != s.charAt(s.length() – 1 – i)){

    return false;

    }

    }

    return true;

    }

    public static void main(String[] args) {

    String str = "A man, a plan, a canal: Panama";

    System.out.println(isValidPalindrome(str));

    }

    }

  5. Jarvis on 2014-9-14

    this is a great solution, thanks for sharing!

  6. April on 2014-10-25

    Here is an easier solution using two pointers

    public static boolean isPalindrome1(String s) {

    s = s.replaceAll(“[^0-9a-zA-Z]”, “”).toLowerCase();

    int start = 0;

    int end = s.length() – 1;

    while (start < end){

    if (s.charAt(start) != s.charAt(end)){

    return false;

    }

    start++;

    end–;

    }

    return true;

    }

  7. ryanlr on 2014-10-27

    Great, Thanks! It is added!

  8. ryanlr on 2014-10-27

    Right. Thanks for pointing out this problem. I have changed the code.

  9. eranyanay on 2014-12-31

    Solution 3 is the most intuitive one when I think of this problem, but you can easily make its performance split in half by doing the iteration from i=0 to s.length() / 2, because at the moment each character is compared twice, i.e for “abcd” you compare “a” == “d” but at the end also “d” == “a”

  10. JOY on 2015-1-7

    I have a question that if the string is empty the statement s.length()==0 would be true, it will return false. Is this wrong?

  11. chenk on 2015-1-31

    public static boolean isPolindrome(String s) {
    s = s.replaceAll(“[^a-zA-Z]”, “”);
    return (s.equalsIgnoreCase(new StringBuilder(s).reverse().toString()));
    }

  12. Tiago Pinho on 2015-3-1

    We could use too ():

    public static boolean isPalindrome(String s) {
    String pureString = s.replaceAll(“[^A-Za-z0-9]”, “”);
    if(pureString.length() == 0)
    return false;
    return(pureString.toLowerCase().equals(new StringBuilder(pureString.toLowerCase()).reverse().toString()));
    }

  13. Chris on 2015-4-1

    Cool!

  14. Arnaud Hebert on 2015-4-19

    Your solution 1 will throw:
    Error:(.. , ..) java: variable left might not have been initialized
    Error:(.. , ..) java: variable right might not have been initialized

    Your solution 3:
    The for loop is not best choice here. You are comparing two times the same character.

    When i = 0,
    you compare charAt(0) with charAt(s.length() – 1)
    When i = s.length() – 1

    you compare charAt(s.length() – 1) and charAt(0)

    While loop is recommended

  15. Sunil Vurity on 2015-6-7

    how about ?

    if (s.Length % 2 != 0)

    {

    return false;

    }

  16. Diego on 2015-10-22

    Hey this is my solution, is not a big deal hehe just a simple for and StringBuilder

    public boolean isPalindrome(String s) {

    s = s.toLowerCase();

    StringBuilder builder = new StringBuilder();

    for(int index = 0; index < s.length(); index++) {

    Character temp = s.charAt(index);

    if(Character.isLetterOrDigit(temp)) {

    builder.append(temp.toString());

    }

    }

    String tempString = builder.toString();

    String otherString = builder.reverse().toString();

    if(tempString.equals(otherString)) return true;

    return false;

    }

  17. Varun Shetty on 2015-12-6

    public class Solution {

    public boolean isPalindrome(String s) {

    s = s.replaceAll(“[^a-zA-Z0-9]”, “”).toLowerCase();

    String rev = new StringBuilder(s).reverse().toString();

    if(s.equals(rev))

    return true;

    else return false;

    }
    }

    How is this is as a solution? Any flaws?

  18. Randy Lutcavich on 2016-6-14

    I still see this error. Also, is there anything wrong with using the StringBuilder()’s reverse method that a couple people have suggested in the comments?

  19. Kshama Dalal on 2016-7-29


    public class palindrom {
    public static boolean isPalindrom(String s){
    int end = s.length()-1;
    for( int i =0 ; i < s.length()/2 ; i++){
    if(s.charAt(i) != s.charAt(end))
    return false;
    end--;
    }
    return true;
    }
    public static void main(String[] args)
    {
    System.out.println(isPalindrom("0madanadam0"));
    }
    }

  20. Ravi Tiwari on 2016-8-7


    static boolean isValidPalidrome(String str) {
    int i = 0;
    int j = str.length() - 1;
    while (i = 'a' && a = 'A' && a <= 'Z')) {
    return true;
    } else {
    return false;
    }
    }

  21. Milan on 2016-9-29

    Solution 3 should stop at s.length()/2 :

    public boolean isPalindrome(String s) {
    s = s.toLowerCase();
    s = s.replaceAll("[^a-z0-9]","");
    for (int i=0; i < s.length()/2; i++){
    if (s.charAt(i) != s.charAt(s.length()-i-1))
    return false;
    }
    return true;
    }

  22. Sumedha Prathipati on 2017-5-30

    Using string buffer ,

    import java.util.*;
    import java.lang.*;
    class Seventeen
    {
    public static void main(String args[])
    {
    Scanner sc=new Scanner(System.in);
    String str=sc.next();
    String reverse = new StringBuffer(str).reverse().toString();
    if(str.equals(reverse))
    System.out.println(“true”);
    else
    System.out.println(“false”);
    }
    }

Leave a comment

*