If n is the length of the input string, your code takes O(n^2) operations. This may surprise you because there are no nested loops in your code, but both the substring method and the += operator for Strings require the creation of a new String, which requires copying its contents.
To see this in action, I have inserted
System.out.println(s);
into the isPalindrome() and checkIfPalindrome() methods, and invoked
isPalindrome("doc, note: i dissent. a fast never prevents a fatness. i diet on cod");
This produces the following output:
docnoteidissentafastneverpreventsafatnessidietoncod
ocnoteidissentafastneverpreventsafatnessidietonco
ocnoteidissentafastneverpreventsafatnessidietonco
cnoteidissentafastneverpreventsafatnessidietonc
cnoteidissentafastneverpreventsafatnessidietonc
noteidissentafastneverpreventsafatnessidieton
noteidissentafastneverpreventsafatnessidieton
oteidissentafastneverpreventsafatnessidieto
oteidissentafastneverpreventsafatnessidieto
teidissentafastneverpreventsafatnessidiet
teidissentafastneverpreventsafatnessidiet
eidissentafastneverpreventsafatnessidie
eidissentafastneverpreventsafatnessidie
idissentafastneverpreventsafatnessidi
idissentafastneverpreventsafatnessidi
dissentafastneverpreventsafatnessid
dissentafastneverpreventsafatnessid
issentafastneverpreventsafatnessi
issentafastneverpreventsafatnessi
ssentafastneverpreventsafatness
ssentafastneverpreventsafatness
sentafastneverpreventsafatnes
sentafastneverpreventsafatnes
entafastneverpreventsafatne
entafastneverpreventsafatne
ntafastneverpreventsafatn
ntafastneverpreventsafatn
tafastneverpreventsafat
tafastneverpreventsafat
afastneverpreventsafa
afastneverpreventsafa
fastneverpreventsaf
fastneverpreventsaf
astneverpreventsa
astneverpreventsa
stneverprevents
stneverprevents
tneverprevent
tneverprevent
neverpreven
neverpreven
everpreve
everpreve
verprev
verprev
erpre
erpre
rpr
rpr
p
p
That's quite a wall of text we are asking the computer to compute! We also see that every String is created twice. That's because you needlessly invoke onlyCharacters() in every iteration.
To avoid creating intermediary String instances, you can use a String Builder:
String onlyCharacters(String s) {
StringBuilder toReturn = new StringBuilder();
for (Character c : s.toCharArray()) {
if (Character.isLetter(c)) {
toReturn.append(c);
}
}
return toReturn.toString();
}
Also, it turns out a StringBuilder has a cool method called reverse(), so we can simplify your program to:
boolean isPalindrome(String s) {
StringBuilder letters = new StringBuilder();
for (Character c : s.toCharArray()) {
if (Character.isLetter(c)) {
letters.append(c);
}
}
StringBuilder reversedLetters = new StringBuilder(letters).reverse();
return onlyLetters.equals(reversedLetters);
}
This code only creates 2 StringBuilder objects rather than n Strings, and is therefore about n/2 times faster than your code.