Problem overview
The method palindromeWords receives an array of words and returns the ones that are palindromes, in the same order. A palindrome reads the same from left to right and from right to left, like "noon". A word with one letter is a palindrome too. If no word is a palindrome, the result is empty. A palindrome that appears twice is kept twice.
For ["pup", "cat", "noon", "dog"] the result is [pup, noon]. For ["a", "bob", "abba", "ab"] it is [a, bob, abba]. For ["kitten", "parrot"] it is [].
Approach: a helper that checks one word
The work is split in two methods. The helper isPalindrome decides about a single word. palindromeWords loops over the array and keeps the words for which the helper says true. The lesson asks you not to use a method that reverses the word. The helper compares the letters from both ends in one loop instead.
The idea: the first letter must equal the last, the second must equal the second from the end, and so on. After checking half of the word, every letter has been compared with its partner. In a word of odd length, the middle letter has no partner and needs no check.
Step by step
- In
isPalindrome, storeword.length()in anintnamedn. - Write a
forloop withistarting at 0, running whilei < n / 2. Division of two ints drops the remainder, so for 5 lettersn / 2is 2. - Inside the loop, compare
word.charAt(i)withword.charAt(n - 1 - i). If they differ, returnfalseat once. One bad pair is enough. - After the loop, return
true. A one-letter word skips the loop and gets here. - In
palindromeWords, create an emptyList<String>namedpalindromes. - Loop over
wordswith aStringnamedword. - If
isPalindrome(word)istrue, addwordtopalindromes. - After the loop, return
palindromes.
The solution in Java
class Solution {
public boolean isPalindrome(String word) {
int n = word.length();
for (int i = 0; i < n / 2; i++) {
if (word.charAt(i) != word.charAt(n - 1 - i)) {
return false;
}
}
return true;
}
public List<String> palindromeWords(String[] words) {
List<String> palindromes = new ArrayList<>();
for (String word : words) {
if (isPalindrome(word)) {
palindromes.add(word);
}
}
return palindromes;
}
}
Some Java details:
word.charAt(i)gives achar, and!=compares two chars by value. That is different from strings, where you must useequals.- The partner of index
iisn - 1 - i. For"noon",nis 4, so index 0 pairs with 3 and index 1 pairs with 2. - The call
isPalindrome(word)already gives aboolean, so it goes straight into theif. Writing== trueadds nothing.
Following the helper on two words
For "noon", n is 4 and the loop runs for i equal to 0 and 1. At i = 0 it compares the first n with the last n: equal. At i = 1 it compares o with o: equal. The loop ends and the helper returns true.
For "cat", n is 3, so n / 2 is 1 and the loop runs once, for i = 0. It compares c with t, finds them different and returns false immediately. The a in the middle is never looked at.
Why a helper is worth it
The loop that compares the letters and the loop that goes over the words do different jobs. Keeping them in two methods means each loop has its own variables and its own return. In particular, the early return false in isPalindrome ends only the check of one word. If both loops lived in one method, that return would end the whole method, and you would need extra flags to carry on with the next word. As two methods, palindromeWords just asks a yes or no question once per word.
Edge cases and common mistakes
- Looping over the whole word. It still works, because each pair is compared twice, but it does double the work.
- Using
n - ias the partner. Indexes start at 0, so the last letter is atn - 1.n - iwould go out of range ati = 0and throw aStringIndexOutOfBoundsException. - Returning
trueinside the loop. One matching pair proves nothing. Only a different pair gives an early answer, andtruecomes after the loop. - Odd lengths.
"abcba"has a middle lettercthat is never compared, and that is correct.
Case and the lesson's inputs
The lesson promises that every word has 1 to 20 lowercase letters, so the helper doesn't need to deal with capitals, spaces or an empty word. The comparison is exact: 'a' and 'A' are different characters, so a word like "Noon" would not count as a palindrome with this code.
Words that appear several times are kept every time. The loop calls the helper once per array item, so a repeated palindrome is added once for each appearance. Nothing in the method removes duplicates.
Finding a bug
If a non-palindrome is kept, look at the helper: the loop may stop too early (for example i < n / 2 - 1), so the last pair is never compared. If a palindrome is missing, the helper may return false too eagerly, such as comparing a letter with the wrong partner. If the order is wrong, look at palindromeWords.
Testing
Running the solution on the three examples gives:
[pup, noon]
[a, bob, abba]
[]
Calling isPalindrome alone on "abcba", "abca" and "a" gives true, false and true.
