Start learning free

LESSON 247 OF 677 · HELPER FUNCTIONS

Palindrome Words in Scala: A Helper That Compares Both Ends

Practice Read the full explanation

You get an array of words, words. Return the words 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.

The work is split between two functions. The first one is a helper. It gets one word and returns true if it is a palindrome, false if not. The second one is the function that is graded. It keeps the words for which the helper returns true.

The helper compares the letters from both ends of the word, in one loop. Don't use a built-in function that reverses the word.

 

Example 1:

Input: words = ["pup", "cat", "noon", "dog"]
Output: ["pup", "noon"]
Explanation: The words "pup" and "noon" read the same both ways.
Read backwards, "cat" is "tac".
Read backwards, "dog" is "god".

Example 2:

Input: words = ["a", "bob", "abba", "ab"]
Output: ["a", "bob", "abba"]
Explanation: The word "a" has one letter, so it is a palindrome.
Read backwards, "ab" is "ba".

Example 3:

Input: words = ["kitten", "parrot"]
Output: []
Explanation: No word reads the same both ways.

 

Constraints:

  • words has at least one word.
  • Every word has 1 to 20 lowercase letters.
  • A word can appear more than once. Each palindrome is kept every time it appears.
STEP 1 OF 8
    Ctrl + Enter to check

    SCALA · HELPER FUNCTIONS

    Palindrome Words in Scala, explained

    Problem overview

    The method palindromeWords gets an Array[String] called words and returns the words that are palindromes, in the same order, as an ArrayBuffer[String]. A palindrome reads the same from left to right and from right to left, like "noon". A word with one letter is a palindrome. A palindrome that appears twice is kept twice, and if there are none the result is empty.

    For ["pup", "cat", "noon", "dog"] the answer is ["pup", "noon"]. For ["a", "bob", "abba", "ab"] it is ["a", "bob", "abba"], and for ["kitten", "parrot"] it is empty.

    Approach

    The work is split between two methods. The helper isPalindrome looks at one word and answers true or false. palindromeWords calls it on every word and keeps the ones that pass. The helper does not reverse the word. It compares the first letter with the last, the second with the one before the last, and so on. One loop over half of the word is enough.

    Why compare pairs

    Think of two fingers, one on the first letter and one on the last. If the letters under them differ, the word cannot be a palindrome. If they match, move both fingers one step inwards and compare again. When the fingers meet or cross, every pair has matched. The loop counter i is the left finger, and n - 1 - i is the right finger, always the same distance from the other end.

    Step by step

    The helper

    1. Store word.length in n, a val.
    2. Loop with for (i <- 0 until n / 2). Each turn checks two letters, so half the word is enough. For 5 letters, n / 2 is 2 (integer division drops the remainder), and the middle letter needs no partner.
    3. Compare word(i) with its partner from the end, word(n - 1 - i). If they differ, return false at once: one different pair is enough.
    4. After the loop, return true. A one-letter word skips the loop and gets here.

    The main method

    1. Create an empty ArrayBuffer[String] called palindromes.
    2. Loop with for (word <- words), from the first word to the last, so the order is kept.
    3. If isPalindrome(word) is true, append the word with +=. The helper's answer is already true or false, so the call goes straight into the if.
    4. Return palindromes.

    The solution in Scala

    class Solution {
        def isPalindrome(word: String): Boolean = {
            val n = word.length
            for (i <- 0 until n / 2) {
                if (word(i) != word(n - 1 - i)) {
                    return false
                }
            }
            return true
        }
    
        def palindromeWords(words: Array[String]): ArrayBuffer[String] = {
            val palindromes = ArrayBuffer[String]()
            for (word <- words) {
                if (isPalindrome(word)) {
                    palindromes += word
                }
            }
            return palindromes
        }
    }
    

    In Scala a string is indexed with parentheses, word(i), not square brackets. The range 0 until n / 2 stops before n / 2, so for "abba" it gives the indices 0 and 1, which pair with 3 and 2.

    The comparisons for two words

    For "abba" the loop makes two comparisons, a with a and b with b, both equal, so the helper returns true. For "abca" the first pair matches (a and a), the second does not (b and c), and the helper returns false there, without looking further.

    Duplicates and order

    The main method never looks at what it already kept, so a palindrome that appears twice is appended twice. That is what the statement asks for. The loop also visits the words from first to last and appends at the end of the buffer, so the kept words come out in their original order without any sorting. When no word passes, nothing is appended and the empty buffer is returned, which is the correct answer.

    Inside the helper, word(i) and word(n - 1 - i) are single characters, and != compares their values. The early return false leaves the helper at once, in the middle of the loop, so the remaining pairs are not checked.

    Testing

    The three examples return pup noon, a bob abba and an empty buffer (the tests print lists as values separated by spaces). The helper alone says isPalindrome("abcba") is true and isPalindrome("abca") is false.

    Another way

    Two indexes that move towards each other do the same job as the loop over half the word:

    def isPalindrome(word: String): Boolean = {
        var left = 0
        var right = word.length - 1
        while (left < right) {
            if (word(left) != word(right)) return false
            left += 1
            right -= 1
        }
        true
    }
    

    On pup, cat, noon, dog and a it returns true, false, true, false, true. It is the "two fingers" picture written literally. The lesson's version needs one variable fewer and cannot get the stopping condition wrong, since the loop count is fixed in advance.

    The library also offers word == word.reverse, which gives true for "noon". This lesson asks for the comparison loop instead, so that you practise indexes and early exits.

    Edge cases and common mistakes

    • Odd length. The middle letter is its own partner, so the loop stops before it. n / 2 does that.
    • Looping over the whole word. It gives the same answer but checks every pair twice.
    • Returning true inside the loop. One matching pair proves nothing. The helper returns true only after all pairs have matched.
    • Off-by-one partner index. The last letter is at n - 1, not n. Asking for word(n) throws a StringIndexOutOfBoundsException, so the partner of index i is word(n - 1 - i).
    • Reversing the word is not allowed here, and the two-ended comparison needs no extra string.
    Keep going with Scala500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free