Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. A palindrome reads the same forwards and backward. For the purpose of this problem, we define empty string as valid palindrome.
Definition:
A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers.
Examples:
Input: "A man, a plan, a canal: Panama"
Output: true
Explanation: "amanaplanacanalpanama"
is a palindrome.
Input: "race a car"
Output: false
Explanation: "raceacar"
is not a palindrome.
Input: " "
Output: true
Explanation: The string becomes empty after removing non-alphanumeric characters, which is a palindrome.
Constraints:
1 <= s.length <= 2 * 10^5
s
consists only of printable ASCII characters.Can you provide an efficient algorithm to determine if a given string meets these palindrome criteria?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The most straightforward way to check if something is a palindrome is to compare it to its reverse. This brute force method means directly reversing the input and checking if it matches the original.
Here's how the algorithm would work step-by-step:
def is_palindrome_brute_force(input_string):
# Create a reversed version of the input string
reversed_string = input_string[::-1]
# Compare the original with the reversed string
# This is the core of the palindrome check
if input_string == reversed_string:
return True
return False
The key is to efficiently compare the input from both ends, skipping irrelevant characters. We effectively ignore anything that isn't a letter or number, focusing only on the characters that matter for palindrome verification. This avoids unnecessary checks and speeds up the process.
Here's how the algorithm would work step-by-step:
def is_palindrome(input_string):
processed_string = ''.join(character.lower() for character in input_string if character.isalnum())
start_index = 0
end_index = len(processed_string) - 1
# Iterate until the pointers meet or cross
while start_index < end_index:
# Comparing characters from both ends
if processed_string[start_index] != processed_string[end_index]:
return False
# Moving pointers towards the center
start_index += 1
end_index -= 1
return True
Case | How to Handle |
---|---|
Null or empty string | Return true, as an empty string is a valid palindrome by definition. |
String with only one character | Return true, as a single character string is also a palindrome. |
String with only non-alphanumeric characters | The pre-processing should reduce the string to empty, so return true. |
String with mixed case alphanumeric characters | Convert the string to lowercase before processing to ensure case-insensitivity. |
String with leading or trailing non-alphanumeric characters | The pre-processing should remove all non-alphanumeric characters at both ends. |
String with all same alphanumeric characters | This is a valid palindrome, so the algorithm should return true. |
String with alphanumeric characters and various non-alphanumeric separators | The pre-processing step must correctly remove all non-alphanumeric characters regardless of position. |
Very long string to test performance | The solution should iterate linearly through the string, and should be efficient for large strings using a two-pointer approach. |