Problem overview
The method palindromeWords receives a list of lowercase 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 one-letter word is a palindrome. A word that appears twice is kept twice, and if no word qualifies the result is an empty list.
For ["pup", "cat", "noon", "dog"] the answer is ["pup", "noon"]. For ["a", "bob", "abba", "ab"] it is ["a", "bob", "abba"]. For ["kitten", "parrot"] it is [].
Approach: a helper for one word
The work is split in two. The helper isPalindrome answers a single question about a single word. palindromeWords then loops over the list and keeps each word for which the helper says True.
To test one word, compare letters in pairs from both ends: the first with the last, the second with the second to last, and so on. One mismatched pair proves the word is not a palindrome. If every pair matches, it is. Only the first half of the word needs to be visited, because each step checks two letters.
The task asks for this loop and not for a built-in way to reverse the word.
Step by step
- In
isPalindrome, storen = len(word). - Loop with
for i in range(n // 2). For 4 letters that isi= 0 and 1; for 5 letters it is 0 and 1 too, since the middle letter needs no partner; for 1 letter it is no turns at all. - Compare
word[i]withword[n - 1 - i]. Fori = 0the partner is the last letter, at indexn - 1. If they differ, returnFalseat once. - After the loop, return
True. - In
palindromeWords, start with an empty listpalindromes. - Loop with
for word in words, and ifself.isPalindrome(word)is true, appendword. - After the loop, return
palindromes.
The solution in Python
class Solution:
def isPalindrome(self, word: str) -> bool:
n = len(word)
for i in range(n // 2):
if word[i] != word[n - 1 - i]:
return False
return True
def palindromeWords(self, words: List[str]) -> List[str]:
palindromes = []
for word in words:
if self.isPalindrome(word):
palindromes.append(word)
return palindromes
Notes:
//is whole-number division.range(5 // 2)isrange(2), andrange(1 // 2)is empty.- For
"noon"the pairs arenwithnandowitho, both equal, so the helper returnsTrue. For"cat"the only pair iscwitht, which differ, so it returnsFalseon the first turn. - The helper's result is already
TrueorFalse, so the call goes straight into theif.
Why the helper helps
The pair-comparing loop is the harder part. Keeping it in its own method means palindromeWords reads almost like the task itself: for each word, if it is a palindrome, keep it. You can also test the helper alone: isPalindrome("racecar") is True and isPalindrome("abca") is False (the outer pair matches, but the inner pair, b and c, does not).
Testing
| words | result |
|---|---|
["pup", "cat", "noon", "dog"] | ["pup", "noon"] |
["a", "bob", "abba", "ab"] | ["a", "bob", "abba"] |
["kitten", "parrot"] | [] |
Common mistakes
- Looping over the whole word. It does twice the work, and gives the same answer.
- Using
word[n - i]. The last index isn - 1, soword[n - 0]is out of range and raisesIndexError. - Returning
Trueinside the loop after the first matching pair. One match proves nothing; only a mismatch is conclusive. - Dropping the final
return True. A palindrome would then returnNone, which counts as false.
