There are a lot of basic problems that have elegant solutions in JavaScript and one of them is checking for Palindromes.
Palindrome is a word, number, phrase, or other string that reads the same backward as it does forward, for example: civic, race car, 123321, etc.
Today we'll learn two ways - the first, which uses built-in JavaScript functions but is a bit slow, and the second, which uses a for loop and performs much better.
Before we proceed with the implementation, we need to know how to remove all non-alphanumeric characters, so if we check the following string "A man, a plan, a canal. Panama" - our function returns true.
The easiest way to do this is to use Regular Expressions:
[\W_]
- to find all non-word characters[^0-9a-z]
- equivalent to the expression above
Matches numbers from the range 0-9, letters from A-Z and a-z and some special characters (underscore is included).
const REGEX_1 = /[\W_]/g;
const REGEX_2 = /[^0-9a-z]/g;
console.log("_civic_".replace(REGEX_1, ""); // "civic"
console.log("_civic_".replace(REGEX_2, ""); // "civic"
As we can see, both Regular Expressions work perfectly fine.
In the following implementation we:
const isPalindrome = value => {
const REGEX = /[\W_]/g;
const cleanValue = value.toLowerCase().replace(REGEX, "");
const reverseValue = cleanValue.split("").reverse().join("");
return cleanValue === reverseValue;
};
isPalindrome("I am not a palindrome"); // false
isPalindrome("_Civic_"); // true
isPalindrome("Race car"); // true
In the following implementation we:
Loop halfway through the length of a value and check if characters from the beginning and end match
Math.floor(5 / 2) is 2, so the iterations are:
1-st: i = 0, cleanValue[0] = c, cleanValue[5 - 1 - 0] = c, match
2-nd: i = 1, cleanValue[1] = i, cleanValue[5 - 1 - 1] = i, match
const isPalindrome = value => {
const REGEX = /[\W_]/g;
const cleanValue = value.toLowerCase().replace(REGEX, "");
const { length } = cleanValue;
for (let i = 0; i < Math.floor(length / 2); i++) {
if (cleanValue[i] !== cleanValue[length - 1 - i]) {
return false;
}
}
return true;
};
isPalindrome("I am not a palindrome"); // false
isPalindrome("_Civic_"); // true
isPalindrome("Race car"); // true
If we measure performance for both implementations, we will see some significant differences, not only for larger values, but also for smaller ones.
The case of a simple "_Civic_" value:
// Way #1 (average from 5 runs)
0.0100000761449337 ms
// Way #2 (average from 5 runs)
0.00500003807246685 ms
// Difference
2 times
The case of a large value (length is equal to 500 000):
// Way #1 (average from 5 runs)
28.234999859705567 ms
// Way #2 (average from 5 runs)
7.844999898225069 ms
// Difference
3.6 times
Obviously, the first way, which is cleaner and easier to read, is a few times slower than the second way with a loop, especially when working with larger strings.
In this article, we learned about two ways to check for palindromes in JavaScript, measured their performance, and found the most optimal way.
There are far more possible implementations, but knowing these two basic ones is a good start to being able to successfully answer this question in an interview.